消息體加密隨著微信服務開發(fā)在越來越多的領(lǐng)域應用,,應用的安全性逐漸被重視起來,。本文主要闡述如何為微信的消息加密的原理與Java版本的實現(xiàn),。 原理做過微信開發(fā)的朋友們都知道,微信使用xml格式的消息結(jié)構(gòu),。這里著重說一下最核心的收發(fā)消息,。 在明文模式中,,POST請求有signature , timestamp , nonce 三個參數(shù),。它的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>
而在加密模式中,,增加了兩個參數(shù):encrypt_type 和 msg_signature 。它的Body 也變更為: - <xml>
- <ToUserName><![CDATA[toUser]]></ToUserName>
- <Encrypt><![CDATA[encryptData]]></Encrypt>
- </xml>
其中encryptData 是加密后的信息,,通過我們在微信開發(fā)平臺配置的EncodingAESKey , Token , 以及自動生成的AppID,,通過加密算法,可以驗證信息的真實性,并且將真實的信息,,解析成如明文的格式的XML,。整條信息是加密的,因此不用擔心被偽造,,否則,,會有風險,。 PS:會有怎樣的風險,?如果是Token被人猜出來進而偽造內(nèi)容,加密模式中的EncodingAESKey不會么,?還是擔心消息類型會泄露,?沒太想明白,希望路過的大神指點 不管怎么說,,加密看起來更安全些,,我現(xiàn)在做一個金融類的項目,有備無患,,就使用了加密的功能,。 代碼實現(xiàn)微信提供了一個各種語言的解析,我在上面稍微封裝了一下: - public class SignUtil {
- /**
- * 與開發(fā)模式接口配置信息中的Token保持一致
- */
- private static String token = "yourToken";
-
- /**
- * 微信生成的 ASEKey
- */
- private static String encodingAesKey ="yourKey";
-
- /**
- * 應用的AppId
- */
- private static String appId="yourId";
-
- /**
- * 解密微信發(fā)過來的密文
- *
- * @return 加密后的內(nèi)容
- */
- 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;
- }
-
- /**
- * 加密給微信的消息內(nèi)容
- * @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的處理方法中調(diào)用: - //request 為請求的 HttpServletRequest 參數(shù)
- 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");
- // 隨機數(shù)
- String nonce = request.getParameter("nonce");
-
- if(SignUtil.checkSignature(signature, timestamp, nonce)) {
- //業(yè)務處理方法,,返回為XML格式的結(jié)果信息 此處需要轉(zhuǎn)換一下編碼,否則中文亂碼,不知為何...
- 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");
- // 隨機數(shù)
- 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());
- //業(yè)務處理方法,,返回為XML格式的結(jié)果信息
- String respMessage = wxService.processRequest(istream,session);
- logger.info("message:"+respMessage);
- String enRespMsg = SignUtil.ecryptMsg(respMessage, timeStamp, nonce);
- return enRespMsg;
- }
- }
使用上面的方法,,可以同時處理明文模式與加密模式,從真正意義上做到閑的蛋疼 如果你覺得這篇文章對你有幫助,,可以順手點個頂,,不但不會喜當?shù)€能讓更多人能看到它...
|