工具类之appSecret、timeStamp、nonce三个参数进行字典排序后SHA1加密,得到signature。

本文介绍了一个用于生成签名的工具类,该工具通过字典排序和SHA1加密算法处理输入的App Secret、时间戳和随机数,以创建一个安全的签名。文章提供了具体的实现代码和使用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先摆上工具类。

 public class SortAndEncryptUtils {
    public static String sortAndEncrypt(String appSecret, String timestamp, String nonce) {
        ArrayList<String> list = new ArrayList<String>();
        list.add(appSecret);
        list.add(timestamp);
        list.add(nonce);
        Collections.sort(list);
        return DigestUtils.shaHex(list.get(0) + list.get(1) + list.get(2));
    }
} 






再提供上DigestUtils的jar包:免费下载通道

摆上一段用法 :
String appSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";  //appSecret
String timestamp = String.valueOf(System.currentTimeMillis() / 1000); //获取系统时间的10位时间戳
String nonce = ""; //随机数
//得到一个三位的随机数
for (int i = 0; i < 3; i++) { nonce += String.valueOf((int) (Math.random() * 10)); }
//得到字典排序并且SHA1加密后的signature。
String signature = SortAndEncryptUtils.sortAndEncrypt(appSecret, timestamp, nonce); 




如有问题请多指正,您的指正使我更正确的前行.




<think>嗯,用户遇到了企业微信服务器验证代码的问题,具体是在解密的时候抛出了SAXParseException,提示“前言中不允许有内容”。我需要先理解这个错误的原因,然后分析用户提供的代码,看看可能哪里出错了。另外,用户还询问了WxCpCryptUtil的初始化方式,以及token、AesKey、CorpId的来源,这部分也需要详细解释。 首先,SAXParseException通常和XML解析有关。用户提到错误发生在plainText = cryptUtil.decrypt(signature, timestamp, nonce, echostr);这一行。这说明在解密echostr时,解密后的内容可能不符合XML格式,导致解析错误。企业微信的服务器验证流程中,echostr应该是一个加密的随机字符串,解密后应该是明文字符串,而不是XML结构。所以可能在解密后,代码尝试将其作为XML解析,而实际上应该是纯文本,从而导致错误。 接下来看用户代码的逻辑。用户使用了WxCpCryptUtil类,并根据echostr是否以"<"开头来选择不同的解密方法。如果echostr是XML格式,使用旧版解密方式;否则用新版。但根据企业微信的最新文档,正确的流程应该是直接调用decrypt(signature, timestamp, nonce, echostr),而这里的条件判断可能存在问题。因为即使echostr被错误地解析为XML,解密后的内容可能还是需要进一步处理。 另外,用户代码中处理echostr的时候,当它包含XML结构时,调用了cryptUtil.decrypt(echostr),这可能是旧版的方法,而新版可能需要不同的参数。这里可能存在版本兼容性问题,或者参数传递错误。比如,旧版方法是否只需要echostr,而新版需要四个参数? 然后,关于WxCpCryptUtil的初始化,用户使用了wxCpService.getWxCpConfigStorage()来获取配置。这说明WxCpCryptUtil需要访问企业微信的配置信息,包括token、AesKey、CorpId。这些参数通常是在系统配置中设置的,比如在Spring Boot的配置文件中,然后通过WxCpService加载到WxCpConfigStorage中。因此,用户需要确认这些配置是否正确,是否与企业微信后台设置的一致,包括编码是否正确,是否有空格或特殊字符。 可能的错误原因有几个方面: 1. **解密方法调用错误**:用户可能在处理不同版本的echostr时,调用了错误的方法。例如,旧版方法可能不适用于当前的企业微信API,或者参数顺序不正确。 2. **XML解析问题**:解密后的echostr可能被错误地当作XML解析,而实际上应该是纯字符串。比如,如果解密后的内容包含特殊字符或格式,导致解析器报错。 3. **配置参数错误**:token、AesKey或CorpId配置不正确,导致解密失败,进而引发异常。 需要检查用户是否正确配置了企业微信的参数,并且确保在解密时使用正确的方法。另外,可能需要查看企业微信的最新文档,确认解密流程是否有变化,或者是否有推荐的解密方式。 关于WxCpCryptUtil的作用,它应该是处理加解密的工具类,使用企业微信提供的token、AesKey和CorpId来验证消息的合法性,并对消息进行解密。这些参数必须与企业微信后台设置的一致,否则无法通过验证。 总结解决步骤: 1. 检查token、AesKey、CorpId是否正确配置,尤其是是否有多余的空格或编码问题。 2. 确认解密方法的调用是否正确,是否需要使用四个参数的方法,并确保参数顺序正确。 3. 如果解密后的内容是纯字符串而非XML,可能需要跳过XML解析步骤,直接返回明文。 4. 查看日志,确认解密后的明文内容是否符合预期,是否有异常字符。 可能用户的条件判断有误,比如echostr是否真的以"<"开头,或者是否应该统一使用四个参数的解密方法。另外,可能需要检查依赖的SDK版本,是否与企业微信的最新API兼容,是否存在已知的bug或需要升级。 最后,建议用户参考官方文档或SDK示例代码,对比解密流程,确保代码逻辑正确。同时,提供详细的日志输出,帮助定位具体是哪个步骤出错。</think>### 问题分析与解决方案 #### 一、`SAXParseException` 错误原因 错误 `org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; 前言中不允许有内容` 的**核心问题在于解密后的 `echostr` 内容不符合 XML 格式**,但代码尝试将其解析为 XML。以下是具体原因和修复步骤: --- ##### 1. 企业微信验证流程解析 企业微信服务器验证的 `echostr` 是一个**加密的随机字符串**,解密后应为**纯文本明文**(例如:`16161481960304128089`),而非 XML 格式。 代码中通过 `cryptUtil.decrypt()` 方法解密后,若直接返回明文即可通过验证。但以下代码逻辑存在问题: ```java if (echostr != null && echostr.startsWith("<")) { plainText = cryptUtil.decrypt(echostr); // ❌ 旧版方法可能尝试解析 XML } else { plainText = cryptUtil.decrypt(signature, timestamp, nonce, echostr); // ✅ 应统一使用此方法 } ``` --- ##### 2. 修复方案 **直接使用新版解密方法**,无需判断 `echostr` 格式: ```java // 统一使用新版解密方法 plainText = cryptUtil.decrypt(signature, timestamp, nonce, echostr); ``` **原因**: 企业微信的 `echostr` 始终是加密字符串,无论是否被 XML 包裹。新版 `decrypt()` 方法已内部处理 XML 解析,若手动判断格式会导致逻辑混乱。 --- #### 二、`WxCpCryptUtil` 的作用与参数来源 ##### 1. `WxCpCryptUtil` 初始化逻辑 ```java WxCpCryptUtil cryptUtil = new WxCpCryptUtil(wxCpService.getWxCpConfigStorage()); ``` - **作用**:通过 `WxCpConfigStorage` 获取企业微信的**配置参数**(Token、AESKey、CorpId),用于消息加解密和签名验证。 - **参数来源**: - **`Token`**:企业微信后台 > 应用管理 > 接收消息 > Token。 - **`AESKey`**:企业微信后台 > 应用管理 > 接收消息 > EncodingAESKey。 - **`CorpId`**:企业微信后台 > 我的企业 > 企业信息 > 企业ID。 - 这些参数通常通过**配置文件**(如 `application.yml`)注入到 `WxCpService` 中。 --- ##### 2. 配置示例(Spring Boot) ```yaml wx: cp: corp-id: your_corp_id agent-id: your_agent_id secret: your_app_secret token: your_token aes-key: your_aes_key ``` - **关键检查点**: 1. 确保 `Token`、`AESKey`、`CorpId` 与企业微信后台配置**完全一致**(包括大小写、无空格)。 2. 确认 `AESKey` 是**43 位**的字符串(例如:`abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG`)。 --- #### 三、完整修复代码 ```java @GetMapping(value = "/toWx", produces = "text/plain;charset=utf-8") public String validateServer( @RequestParam("msg_signature") String signature, @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce, @RequestParam(value = "echostr", required = false) String echostr) { logger.info("收到验证请求:signature={}, timestamp={}, nonce={}, echostr={}", signature, timestamp, nonce, echostr); try { WxCpCryptUtil cryptUtil = new WxCpCryptUtil(wxCpService.getWxCpConfigStorage()); // 统一使用新版解密方法 String plainText = cryptUtil.decrypt(signature, timestamp, nonce, echostr); logger.info("验证成功,明文内容:{}", plainText); return plainText; } catch (Exception e) { logger.error("验证失败:", e); return "ERROR: " + e.getMessage(); } } ``` --- #### 四、常见错误排查 1. **参数不一致**:检查 `Token`、`AESKey`、`CorpId` 是否与后台配置一致。 2. **AESKey 格式错误**:确认 `AESKey` 长度为 43 位。 3. **依赖版本问题**:使用最新版 `weixin-java-cp` 依赖(推荐 4.5.0+)。 4. **日志调试**:在解密前后打印原始 `echostr` 和解密后的 `plainText`,确认明文为纯数字或字符串。 --- #### 五、数学公式补充(验证逻辑) 企业微信验证签名的公式为: $$ \text{签名} = \text{SHA1}( \text{Token} \| \text{timestamp} \| \text{nonce} \| \text{解密后的 echostr} ) $$ 若计算出的签名与请求中的 `signature` 一致,则验证通过。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值