加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

微信开发(五)微信消息加解密 (EncodingAESKey)

发布时间:2020-12-16 09:16:21 所属栏目:百科 来源:网络整理
导读:文章作者: 松阳 本文出自 阿修罗道 ,禁止用于商业用途,转载请注明出处。 原文链接: http://www.jb51.cc/article/p-dnohbbpw-eg.html 消息体加密 随着微信服务开发在越来越多的领域应用,应用的安全性逐渐被重视起来。本文主要阐述如何为微信的消息加密的


文章作者:松阳

本文出自 阿修罗道,禁止用于商业用途,转载请注明出处。

原文链接:http://www.52php.cn/article/p-dnohbbpw-eg.html







消息体加密

随着微信服务开发在越来越多的领域应用,应用的安全性逐渐被重视起来。本文主要阐述如何为微信的消息加密的原理与Java版本的实现。

原理

做过微信开发的朋友们都知道,微信使用xml格式的消息结构。这里着重说一下最核心的收发消息。

在明文模式中,POST请求有signature,timestamp,nonce三个参数。它的Body为一个XML:

<xml>
    <ToUserName><![CDATA[toUser]]></ToUserName>
    <FromUserName><![CDATA[fromUser]]></FromUserName> 
    <CreateTime>1348831860</CreateTime>
    <MsgType><![CDATA[text]]></MsgType>
    <Content><![CDATA[this is a test]]></Content>
    <MsgId>1234567890123456</MsgId>
</xml>

而在加密模式中,增加了两个参数:encrypt_typemsg_signature 。它的Body 也变更为:

<xml>
    <ToUserName><![CDATA[toUser]]></ToUserName>
    <Encrypt><![CDATA[encryptData]]></Encrypt>
</xml>

其中encryptData是加密后的信息,通过我们在微信开发平台配置的EncodingAESKey,Token,以及自动生成的AppID,通过加密算法,可以验证信息的真实性,并且将真实的信息,解析成如明文的格式的XML。整条信息是加密的,因此不用担心被伪造,否则,会有风险。

PS:会有怎样的风险?如果是Token被人猜出来进而伪造内容,加密模式中的EncodingAESKey不会么?还是担心消息类型会泄露?没太想明白,希望路过的大神指点

不管怎么说,加密看起来更安全些,我现在做一个金融类的项目,有备无患,就使用了加密的功能。

代码实现

微信提供了一个各种语言的解析,我在上面稍微封装了一下:

public class SignUtil {
    /**
     *  与开发模式接口配置信息中的Token保持一致
     */
    private static String token = "yourToken";
    
    /**
     * 微信生成的 ASEKey
     */
    private static String encodingAesKey ="yourKey";

    /**
     * 应用的AppId
     */
    private static String appId="yourId";
    
    /**
     * 解密微信发过来的密文
     * 
     * @return 加密后的内容
     */
    public static String decryptMsg(String msgSignature,String timeStamp,String nonce,String encrypt_msg) {
        WXBizMsgCrypt pc;
        String result ="";
        try {
            pc = new WXBizMsgCrypt(token,encodingAesKey,appId);
            result = pc.decryptMsg(msgSignature,timeStamp,nonce,encrypt_msg);
        } catch (AesException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 加密给微信的消息内容
     * @param replayMsg
     * @param timeStamp
     * @param nonce
     * @return
     */
    public static String ecryptMsg(String replayMsg,String nonce) {
        WXBizMsgCrypt pc;
        String result ="";
        try {
            pc = new WXBizMsgCrypt(token,appId);
            result = pc.encryptMsg(replayMsg,nonce);
        } catch (AesException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return result;
    }

最后,在对应POST的处理方法中调用:

//request 为请求的 HttpServletRequest 参数
String encrypt_type =request.getParameter("encrypt_type");
if (encrypt_type == null || encrypt_type.equals("raw")) { //不用加密
    // 微信加密签名  
    String signature = request.getParameter("signature");  
    // 时间戳  
    String timestamp = request.getParameter("timestamp");  
    // 随机数  
    String nonce = request.getParameter("nonce");  
      
    if(SignUtil.checkSignature(signature,timestamp,nonce)) {
        //业务处理方法,返回为XML格式的结果信息 此处需要转换一下编码,否则中文乱码,不知为何... 
        String respMessage = new String(wxService.processRequest(request.getInputStream(),session).getBytes("UTF-8"),"ISO8859_1");  
        logger.info("message:"+respMessage);
        return respMessage;      
    } else {
        return "check Error";
    }
} else {//需走加解密流程    
    // 微信加密签名  
    String msgSignature = request.getParameter("msg_signature");  
    // 时间戳  
    String timeStamp = request.getParameter("timestamp");  
    // 随机数  
    String nonce = request.getParameter("nonce");
    //密文
    String encryptMsg = readLine(request.getInputStream());
  
    String data = SignUtil.decryptMsg(msgSignature,encryptMsg);
    logger.info("parse Data is:"+data);
    if(data.length() == 0) {
        return "CheckError";
    } else {
        InputStream istream = new ByteArrayInputStream(data.getBytes());
        //业务处理方法,返回为XML格式的结果信息
        String respMessage = wxService.processRequest(istream,session);
        logger.info("message:"+respMessage);
        String enRespMsg = SignUtil.ecryptMsg(respMessage,nonce);
        return enRespMsg;
    }
}

使用上面的方法,可以同时处理明文模式与加密模式,从真正意义上做到闲的蛋疼

如果你觉得这篇文章对你有帮助,可以顺手点个,不但不会喜当爹,还能让更多人能看到它...

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读