消息加密模式有三种,如下图:
在明文模式下我们不需要解密,但如果是加密模式提交的,我们要对得到的数据进行解密才能使用。
一、首先要到官方网站下载示例文件。
1.拷贝包src.com.qq.weixin.mp.aes下的java类
2.拷贝jar包:commons-codec-1.9.jar
3.官方说明:
提供接收和推送给公众平台消息的加解密接口(UTF8编码的字符串).
第三方回复加密消息给公众平台
第三方收到公众平台发送的消息,验证消息的安全性,并对消息进行解密。
说明:异常java.security.InvalidKeyException:illegal Key Size的解决方案
在官方网站下载JCE无限制权限策略文件:
下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt
如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件
如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件
注:这里说明一下,我使用的是jdk 1.7.0_45且jdk安装在d盘,替换的jre路径为:
D:\Program Files\Java\jdk1.7.0_45\jre\lib\security
二、在MessageUtil.java中添加解析加密文件的代码:
----MessageUtil.java:
/**
* 对加密模式提交的配置进行解密处理
* 2015-09-03
* @param req
* @return
* @throws Exception
*/
public static Map<String, String> parseEncryptXml(HttpServletRequest req) throws Exception{
//保存要处理的加密文件
Map<String, String> map = new HashMap<String, String>();
//用InputStream来存放要处理的数据
InputStream is = req.getInputStream();
//读取InputStream中的数据(xml)
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
StringBuffer sb = new StringBuffer();
String line = br.readLine();
while(line != null) {
sb.append(line);
}
//进行解密
String msgSignature = req.getParameter("msg_signature");
String timeStamp = req.getParameter("timestamp");
String nonce = req.getParameter("nonce");
//微信官方提供的工具
//WXBizMsgCrypt的三个属性:
//String token, String encodingAesKey, String appId
WXBizMsgCrypt msgCrypt = new WXBizMsgCrypt("token", "encodingAesKey", "appId");
String msgXml = msgCrypt.decryptMsg(msgSignature, timeStamp, nonce, sb.toString());
//使用dom4j工具对xml文件进行解析
Document document = DocumentHelper.parseText(msgXml);
//从根元素开始解析
Element root = document.getRootElement();
//递归解析
map = recursiveParseXML(map, root);
//释放资源
is.close();
is = null;
return map;
}
三、在CoreServlet.java类中的doPost()中添加代码,处理加密的消息:
----CoreServlet.java:
/**
* 接收微信服务器请求处理的内容
* 交给CoreService类处理
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置字符集 微信默认的为UTF-8
//请求
request.setCharacterEncoding("utf-8");
//响应
response.setCharacterEncoding("utf-8");
try{
/**
* 对三种加密方式进行解析
* 明文模式
* 兼容模式
* 安全模式
*/
//加密方式
String encryptType = request.getParameter("encrypt_type");
//时间戳
String timestamp = request.getParameter("timestamp");
//随机数
String nonce = request.getParameter("nonce");
//定义一个Map来接收请求的xml文件
Map<String, String> requestMap = null;
//响应回去的xml文件
String responseXml = null;
//以安全模式提交的数据
if("aes".equals(encryptType)) {
//
requestMap = MessageUtil.parseEncryptXml(request);
//要响应的xml文件
responseXml = CoreService.proce***equest(requestMap);
//进行加密
WXBizMsgCrypt msgCrypt = new WXBizMsgCrypt("token", "encodingAesKey", "appId");
//响应加密后的xml文件
responseXml = msgCrypt.encryptMsg(responseXml, timestamp, nonce);
}
//以明文模式提交过来的,不需要解密
else {
//处理接收到的消息
requestMap = MessageUtil.parseXML(request);
responseXml = CoreService.proce***equest(requestMap);
}
//向服务器相关响应信息
PrintWriter out = response.getWriter();
out.print(responseXml);
out.close();
}catch(Exception e) {
e.printStackTrace();
}
}
---------------------------完毕---------------------------
转载于:https://blog.51cto.com/chn0515/1691201