zoukankan      html  css  js  c++  java
  • 微信开发(五)微信消息加解密 (EncodingAESKey)

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

    版权声明:本文为 松阳 (blog.csdn.net/fansongy) 原创文章,转载必须注明出处: https://blog.csdn.net/fansongy/article/details/44005301

    文章作者:松阳

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

    原文链接:http://blog.csdn.net/fansongy/article/details/44005301


    消息体加密
    随着微信服务开发在越来越多的领域应用,应用的安全性逐渐被重视起来。本文主要阐述如何为微信的消息加密的原理与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_type 和 msg_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 timeStamp, String nonce) {
    WXBizMsgCrypt pc;
    String result ="";
    try {
    pc = new WXBizMsgCrypt(token, encodingAesKey, appId);
    result = pc.encryptMsg(replayMsg, timeStamp, 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, timeStamp, nonce, 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, timeStamp, nonce);
    return enRespMsg;
    }
    }
    使用上面的方法,可以同时处理明文模式与加密模式,从真正意义上做到闲的蛋疼

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

    ---------------------
    作者:松阳
    来源:CSDN
    原文:https://blog.csdn.net/fansongy/article/details/44005301
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    十分钟-Nginx 入门到上线
    83.面向忙碌开发者的 Android 知识点收录 (转)
    技术人,为什么需要构建知识图谱 (转载)
    C# 4.0四大新特性代码示例与解读
    .NET 项目代码风格要求
    .NET 推荐博客
    C# 五、谈扩展方法的理解
    ASP.NET 一步步开发自己的博客 .NET版(11、Web.config文件的读取和修改)
    ASP.NET 你必须知道的EF知识和经验
    Linq表达式、Lambda表达式你更喜欢哪个?
  • 原文地址:https://www.cnblogs.com/handsome1013/p/10470558.html
Copyright © 2011-2022 走看看