消息加密模式有三种,如下图:
在明文模式下我们不需要解密,但如果是加密模式提交的,我们要对得到的数据进行解密才能使用。
一、首先要到官方网站下载示例文件。
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.processRequest(requestMap); //进行加密 WXBizMsgCrypt msgCrypt = new WXBizMsgCrypt("token", "encodingAesKey", "appId"); //响应加密后的xml文件 responseXml = msgCrypt.encryptMsg(responseXml, timestamp, nonce); } //以明文模式提交过来的,不需要解密 else { //处理接收到的消息 requestMap = MessageUtil.parseXML(request); responseXml = CoreService.processRequest(requestMap); } //向服务器相关响应信息 PrintWriter out = response.getWriter(); out.print(responseXml); out.close(); }catch(Exception e) { e.printStackTrace(); } }
---------------------------完毕---------------------------