微信公衆號開發-----驗證消息的確來自微信服務器(明文模式下)

閱讀本文前,請先認真閱讀微信官方文檔:微信公衆號技術文檔之接入指南

接入概述

接入微信公衆平臺開發,開發者需要按照如下步驟完成:

1、填寫服務器配置

2、驗證服務器地址的有效性

3、依據接口文檔實現業務邏輯

本文主要介紹第二個步驟的代碼實現。

第二步:驗證消息的確來自微信服務器

  1. 開發者提交信息後,微信服務器將發送GET請求到填寫的服務器地址URL上
    (由於消息加解密方式選擇的爲明文模式,需加密模式時從官方文檔下載Java部分代碼,去除註釋部分代碼即可)

    /**
     * 消息加解密接入
     */
    public class EntryController extends Controller {
    
        public void accept() throws IOException {
            String method = getRequest().getMethod();
            if ("GET".equals(method)) {
                doGet();//開發者模式驗證
            }else {
                doPost();//接收消息
            }
        }
    
        /*
         * 響應get請求,微信默認token校驗時使用get請求
         */
        private void doGet(){
            //接收微信用來校驗信息的內置規定參數
            String msgSignature =getPara("signature");   // 微信加密簽名
            String timeStamp = getPara("timestamp");  // 時間戳
            String nonce = getPara("nonce"); // 隨機數
            String echoStr = getPara("echostr"); // 隨機字符串
    
            //// 創建加密類
            //WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(WechartConst.Token, WechartConst.EncodingAESKey,WechartConst.appId);
            // // 比對msgSignature 用token, timeStamp, nonce加密的參數是否一致,一致證明該接口來自微信,異常則不是來自微信
            //String echostr = wxcpt.verifyUrl(msgSignature, timeStamp, nonce, echoStr);
    
            // 通過檢驗signature對請求進行校驗,若校驗成功則原樣返回echostr,表示接入成功,否則接入失敗
            //獲取微信服務器中配置的Token的值
            String token = SystemConfig.WECHAT_TOKEN;
            if (WechatUtil.checkSignature(msgSignature,token, timeStamp, nonce)){
                //原樣返回echostr參數內容
                renderJson(echoStr);
            }
        }
    }
    
  2. 開發者通過檢驗signature對請求進行校驗(下面有校驗方式)。若確認此次GET請求來自微信服務器,請原樣返回echostr參數內容,則接入生效,成爲開發者成功,否則接入失敗。加密/校驗流程如下:
    1)將token、timestamp、nonce三個參數進行字典序排序
    2)將三個參數字符串拼接成一個字符串進行sha1加密
    3)開發者獲得加密後的字符串可與signature對比,標識該請求來源於微信

    public class WechatUtil {
     	/**
         * 驗證消息的確來自微信服務器
         * @param msgSignature 微信加密簽名
         * @param token 開發者填寫的token參數
         * @param timeStamp 時間戳
         * @param nonce 隨機數
         * @return
         * @throws
         */
        public static boolean checkSignature(String msgSignature, String token,String timeStamp, String nonce) {
    
                // 1.將token、timestamp、nonce三個參數進行字典序排序
                String[] arr = new String[]{token, timeStamp, nonce};
                Arrays.sort(arr);
    
                // 2. 將三個參數字符串拼接成一個字符串進行sha1加密
                StringBuilder content = new StringBuilder();
                for (int i = 0; i < arr.length; i++) {
                    content.append(arr[i]);
                }
                MessageDigest md = null;
                String tmpStr = null;
                try {
                    md = MessageDigest.getInstance("SHA-1");
                    // 將三個參數字符串拼接成一個字符串進行sha1加密
                    byte[] digest = md.digest(content.toString().getBytes());
                    tmpStr = BytesParserUtil.byteToStr(digest);
                } catch (NoSuchAlgorithmException e) {
                    e.printStackTrace();
                }
    
                // 3.將sha1加密後的字符串可與signature對比,標識該請求來源於微信
                return tmpStr != null ? tmpStr.equals(msgSignature.toUpperCase()) : false;
            }
    }
    

    注:代碼中使用到的工具類請參考: 字節轉換工具---- BytesParserUtil

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章