微信公众平台开发之对加密模式的解密

消息加密模式有三种,如下图:


微信公众平台开发之对加密模式的解密


在明文模式下我们不需要解密,但如果是加密模式提交的,我们要对得到的数据进行解密才能使用。


一、首先要到官方网站下载示例文件。

       点这里下载...

       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();
  }
 }


---------------------------完毕---------------------------



本文出自 “顽强的石头” 博客,请务必保留此出处http://chn0515.blog.51cto.com/10646281/1691201

微信公众平台开发之对加密模式的解密

上一篇:[Typescript] “Record” Mapped Type


下一篇:[微信营销企划之路]003.Access forbidden!