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

div#cpmenu {height:200px;float:left;}
div#cpcontent {height:200px;width:150px;float:left;}

文章作者:松阳

原文链接: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_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 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;
    }
}

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

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

时间: 2024-12-19 18:15:25

微信开发(五)微信消息加解密 (EncodingAESKey)的相关文章

【PHP】微信开放平台---消息加解密-php7.1 使用openssl代替Mcrypt

1.问题 微信开发小程序消息加解密,官方给出的dome中使用正常,最近升级了7.1发现接收消息不能解密了,最后查了日志又查了各种资料发现 Mcrypt 函数php7.1已经被废弃: 2.解决方式 在Prpcrypt类中使用openssl代替Mcrypt 官方代码: /** * 对密文进行解密 * @param string $encrypted 需要解密的密文 * @return string 解密得到的明文 */ public function decrypt($encrypted, $app

使用delphi+intraweb进行微信开发4—微信消息加解密

在上一讲当中我做了个简单的微信文本消息回显应用,当时是以微信明文方式实现的,其实微信推荐的是消息应该加密传输以增加安全性,所以这讲说说微信消息的加解密. 在微信的帮助页面上可以下载微信消息加解密的例程,可惜的是没有Delphi语言的示例,网上搜索一番,没有人贡献出写好的Delphi版的微信加解密算法单元,好在有官方示例的C#版的,那就按照C#的改一个吧. 微信消息是以AES算法进行的加密处理,而遗憾的是Delphi并没有内置的AES算法单元,必须找第三方实现的,不过一般第三方实现的算法都因为种种

微信公众号开发教程[005]-消息管理-消息加解密

一.配置公众号消息加解密方式 在公众号官方管理后台->开发->基本配置->修改配置上有3种方式,如下: 其中,EncodingAESKey可以随机生成. 加解密方式说明: 1).明文模式:微信服务器向公众号服务器(即我们要处理的http://szuzsq.tunnel.qydev.com/weixin/index.php)发送的xml结构是原始的,没有加密.如下: <xml> <ToUserName><![CDATA[gh_733c42e0aee9]]>

C#开发微信.NET平台MVC微信开发 发送普通消息Demo以及收不到消息的问题

不得不说现在微信非常火,微信开放平台可以自己写程序跟用户交互,节省了前台开发成本,免去用户装客户端的烦恼.于是今天兴致来潮,想做一个试试. 首先找到了开发者文档,看了看,蛮简单的.(公众号早已申请,有兴趣可以关注看看:zyjsoft) 第一步(提供接口,供微信调用,由于是HTTP请求,于是我用MVC模式做了一个简单的接口): //认证接口 public ActionResult WeiXin(string signature, string timestamp, string nonce, st

微信开发SDK|微信sdk使用教程--手机客户端微信下线通知服务端

微信开发SDK|微信sdk使用教程--手机客户端微信下线通知服务端 case WeChatOfflineNotice: {// 手机客户端微信下线通知 log.debug("socket:msgtype=WeChatOfflineNotice"); weChatOfflineNoticeHandler.handleMsg(ctx, msgVo); break; } package com.jubotech.framework.netty.handler.socket; import o

微信开发——申请微信支付功能及支付环境设置

很久没写博客文章了,最近一直负责微信开发实现微信支付功能,所以在这方面有一定的了解. 在开始实现微信支付功能的前提是公众号已认证的并已通过审核的服务号,具体微信支付申请人的流程没有比官 方公布的流程更详细的了,附上链接https://mp.weixin.qq.com/paymch/readtemplate?t=mp/business/faq_tmpl,开通 并与微信工作人员沟通微信支付相关授权路径之后,在微信后台可以看到微信支付的相关功能 在支付申请选择下可以查看商户的基本资料以及我们开发支付功

夺命雷公狗---微信开发23----客服消息接口基础和推送文本

我们这边课程里面一共用到了三个文件,分别是WeChat.class.php和common.php以及index.php 我们在写这个功能之前也要学会查手册,手册我们可以在微信开发这里找到,如下所示: 点击进去后我们将会看到客服接口,我们可以点击下进去看看里面有什么动动 这里有一个发送文本消息的,我们点击进去看下 这里很明显就看到文本消息是通过一个json数据来进行实现的,废话不多说,开工 这里我们先来写一个WeChat.php的文件,这里作用主要适用于封装一个CURL上传类的,代码如下所示: <

第 6 章 微信开发之各种消息的接收与响应

一.在哪里接收这些消息 从微信公众平台接口消息指南中可以了解到,当用户向公众帐号发消息时,微信服务器会将消息通过POST方式提交给我们在接口配置信息中填写的URL,而我们就需要在URL所指向的请求处理类CoreServlet的doPost方法中接收消息.处理消息和响应消息. /** * 处理微信服务器发来的消息 */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws Servle

关于微信开发与微信支付更新

1.)微信开发一般就是看文档,按部就班调用API就行,这里推荐一些SDK .NET https://github.com/JeffreySu/WeiXinMPSDK JAVA http://git.oschina.net/pyinjava/fastweixin NodeJS https://github.com/node-weixin/node-weixin-api Python http://git.oschina.net/jeffkit/wechat 2.)在之前的文章微信支付[v3]中,说