1. 程式人生 > >微信JS SDK使用許可權簽名演算法 jsapi_ticket

微信JS SDK使用許可權簽名演算法 jsapi_ticket

生成簽名之前必須先了解一下jsapi_ticket,jsapi_ticket是公眾號用於呼叫微信JS介面的臨時票據。正常情況下,jsapi_ticket的有效期為7200秒,通過access_token來獲取。由於獲取jsapi_ticket的api呼叫次數非常有限,頻繁重新整理jsapi_ticket會導致api呼叫受限,影響自身業務,開發者必須在自己的服務全域性快取jsapi_ticket 。

獲取signature主要分四部

  • 1、使用APPID和APPSecret獲取access_token;

  • 2、使用access_token獲取jsapi_ticket ;

  • 3、用時間戳、隨機數、jsapi_ticket和要訪問的url按照簽名演算法拼接字串;

  • 4、對第三步的字串進行SHA1加密,得到簽名。

注意事項

  • 簽名用的noncestr和timestamp必須與wx.config中的nonceStr和timestamp相同。
  • 簽名用的url必須是呼叫JS介面頁面的完整URL。
  • 出於安全考慮,開發者必須在伺服器端實現簽名的邏輯。

參考以下文件獲取access_token(有效期7200秒,開發者必須在自己的服務全域性快取access_token):
用第一步拿到的access_token 採用http GET方式請求獲得jsapi_ticket(有效期7200秒,開發者必須在自己的服務全域性快取jsapi_ticket):

https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
成功返回如下JSON:

{
"errcode":0,
"errmsg":"ok",
"ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
"expires_in":7200
}

獲得jsapi_ticket之後,就可以生成JSSDK許可權驗證的簽名了。

簽名演算法

簽名生成規則如下:參與簽名的欄位包括noncestr(隨機字串), 有效的jsapi_ticket, timestamp(時間戳), url(當前網頁的URL,不包含#及其後面部分) 。對所有待簽名引數按照欄位名的ASCII 碼從小到大排序(字典序)後,使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字串string1。這裡需要注意的是所有引數名均為小寫字元。對string1作sha1加密,欄位名和欄位值都採用原始值,不進行URL 轉義。

即signature=sha1(string1)。 示例:

noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
timestamp=1414587457
url=http://mp.weixin.qq.com

步驟1. 對所有待簽名引數按照欄位名的ASCII 碼從小到大排序(字典序)後,使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字串string1:

jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&timestamp=1414587457&url=http://mp.weixin.qq.com

步驟2. 對string1進行sha1簽名,得到signature:

f4d90daf4b3bca3078ab155816175ba34c443a7b

JS程式碼

wx.config({  
    debug: true, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。  
    appId: '', // 必填,公眾號的唯一標識  
    timestamp: , // 必填,生成簽名的時間戳  
    nonceStr: '', // 必填,生成簽名的隨機串  
    signature: '',// 必填,簽名,見附錄1  
    jsApiList: [] // 必填,需要使用的JS介面列表,所有JS介面列表見附錄2  
});  

後端程式碼


   //生成隨機字串用的
    private static final String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

   /**
     * @Description: XiaoYeUtil.createNonceStr
     * @Author: ChenYao
     * @Param: []
     * @Return: java.lang.String
     * @Version: 1.0
     * @Create: Date Time: 2018/12/7
     * @Update: Date Time: 2018/12/7
     * @see:
     * @Note:建立隨機串 自定義個數0 < ? < 32
     */

    public static String createNonceStr() {
        String nonceStr = "";
        for (int i = 0; i < 16; i++) {
            int beginIndex = (int) Math.round(Math.random() * 10);
            nonceStr += str.substring(beginIndex, beginIndex + 1);
        }
        return nonceStr;
    }

   /**
     * @Description: XiaoYeUtil.createSignature
     * @Author: ChenYao
     * @Param: [nocestr, ticket, timestamp, url]
     * @Return: java.lang.String
     * @Version: 1.0
     * @Create: Date Time: 2018/12/7
     * @Update: Date Time: 2018/12/7
     * @see:
     * @Note:資料簽名
     */
    public static String createSignature(String nocestr, String ticket, String timestamp, String url) {
        // 這裡引數的順序要按照 key 值 ASCII 碼升序排序
        String s = "jsapi_ticket=" + ticket + "&noncestr=" + nocestr
                + "&timestamp=" + timestamp + "&url=" + url;
        return SHA1(s);
    }
  /**
     * @Description: XiaoYeUtil.SHA1
     * @Author: ChenYao
     * @Param: [decript]
     * @Return: java.lang.String
     * @Version: 1.0
     * @Create: Date Time: 2018/12/9
     * @Update: Date Time: 2018/12/9
     * @see:
     * @Note:加密
     */
  public static String SHA1(String decript) {
        try {
            MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1");
            digest.update(decript.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 位元組陣列轉換為 十六進位制 數
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }
//時間戳,10位!!10位!!10位!!
        String timestamp = String.format("%010d", System.currentTimeMillis() / 1000);