zoukankan      html  css  js  c++  java
  • 微信客户端sdk使用前的 授权签名

    http://1017401036.iteye.com/blog/2263358 

    微信的JS-SDK通过config接口注入权限验证配置,官网上的文档说的很清楚:

    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: '', // 必填,公众号的唯一标识
        timestamp: , // 必填,生成签名的时间戳
        nonceStr: '', // 必填,生成签名的随机串
        signature: '',// 必填,签名,见附录1
        jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
    });

     上面的几个参数,对于像我这样子的初学者而言,不简单,所以在弄这块的时候没少碰钉子,这里说一下。

    先说那个最烦人的signature,官网附录1是这么说的:

    -------------------------------------------------------------------------------------------------------------------------------------

    jsapi_ticket

    生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。

    1、参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):../15/54ce45d8d30b6bf6758f68d2e95bc627.html

    2、用第一步拿到的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之后,就可以生成JS-SDK权限验证的签名了。

    签名算法

    签名生成规则如下:参与签名的字段包括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?params=value

    步骤1. 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:

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

    步骤2. 对string1进行sha1签名,得到signature:

    0f9de62fce790f9a083d5c99e95740ceb90c27ed

    注意事项:

    1、签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
    2、签名用的url必须是调用JS接口页面的完整URL。
    3、出于安全考虑,开发者必须在服务器端实现签名的逻辑。

    -------------------------------------------------------------------------------------------------------------------------------------

    以上的东西加起来就是四步:

    1、使用APPID和APPSecret获取access_token;

    2、使用access_token获取jsapi_ticket ;

    3、用时间戳、随机数、jsapi_ticket和要访问的url按照签名算法拼接字符串;

    4、对第三步的字符串进行SHA1加密,得到签名。

    第一步、获取access_token

    这里是官网的说法,可以看看。

    以下是我的代码实现:

    public static String getAccessToken() {
        String access_token = "";
        String grant_type = "client_credential";//获取access_token填写client_credential 
        String AppId="APPID";//第三方用户唯一凭证
        String secret="APPSECRET";//第三方用户唯一凭证密钥,即appsecret 
        //这个url链接地址和参数皆不能变
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type="+grant_type+"&appid="+AppId+"&secret="+secret;
         
        try {
            URL urlGet = new URL(url);
            HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
            http.setRequestMethod("GET"); // 必须是get方式请求
            http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
            http.setDoOutput(true);
            http.setDoInput(true);
            System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
            System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
            http.connect();
            InputStream is = http.getInputStream();
            int size = is.available();
            byte[] jsonBytes = new byte[size];
            is.read(jsonBytes);
            String message = new String(jsonBytes, "UTF-8");
            JSONObject demoJson = JSONObject.fromObject(message);
            System.out.println("JSON字符串:"+demoJson);
            access_token = demoJson.getString("access_token");
            is.close();
        } catch (Exception e) {
                e.printStackTrace();
        }
        return access_token;
    }

    APPID和APPSECRET可以去微信公众平台---“开发----基本配置”中查找。

    第二步、获取jsapi_ticket

    public static String getTicket(String access_token) {
        String ticket = null;
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ access_token +"&type=jsapi";//这个url链接和参数不能变
        try {
            URL urlGet = new URL(url);
            HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
            http.setRequestMethod("GET"); // 必须是get方式请求
            http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
            http.setDoOutput(true);
            http.setDoInput(true);
            System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
            System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
            http.connect();
            InputStream is = http.getInputStream();
            int size = is.available();
            byte[] jsonBytes = new byte[size];
            is.read(jsonBytes);
            String message = new String(jsonBytes, "UTF-8");
            JSONObject demoJson = JSONObject.fromObject(message);
            System.out.println("JSON字符串:"+demoJson);
            ticket = demoJson.getString("ticket");
            is.close();
        } catch (Exception e) {
                e.printStackTrace();
        }
        return ticket;
    }

    拿到了jsapi_ticket之后就要参数名排序和拼接字符串,并加密了。以下为sha1的加密算法:

    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 "";
    }

    加密算法转载自:http://www.open-open.com/lib/view/open1392185662160.html

    获取签名:

    public static void main(String[] args) {
    	//1、获取AccessToken
    	String accessToken = getAccessToken();
    	
    	//2、获取Ticket
    	String jsapi_ticket = getTicket(accessToken);
    	
    	//3、时间戳和随机字符串
    	String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//随机字符串
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//时间戳
        
        System.out.println("accessToken:"+accessToken+"
    jsapi_ticket:"+jsapi_ticket+"
    时间戳:"+timestamp+"
    随机字符串:"+noncestr);
        
        //4、获取url
        String url="http://www.luiyang.com/add.html";
        /*根据JSSDK上面的规则进行计算,这里比较简单,我就手动写啦
        String[] ArrTmp = {"jsapi_ticket","timestamp","nonce","url"};
        Arrays.sort(ArrTmp);
        StringBuffer sf = new StringBuffer();
        for(int i=0;i<ArrTmp.length;i++){
        	sf.append(ArrTmp[i]);
        }
        */
        
        //5、将参数排序并拼接字符串
        String str = "jsapi_ticket="+jsapi_ticket+"&noncestr="+noncestr+"&timestamp="+timestamp+"&url="+url;
       
        //6、将字符串进行sha1加密
        String signature =SHA1(str);
        System.out.println("参数:"+str+"
    签名:"+signature);
    }

     该要的都有了,再次回到最开始的config配置,此时应该为:

    wx.config({
        debug: true, //调试阶段建议开启
        appId: "APPID",//APPID
        timestamp: "timestamp",//上面main方法中拿到的时间戳timestamp
        nonceStr: "nonceStr",//上面main方法中拿到的随机数nonceStr
        signature: "signature",//上面main方法中拿到的签名signature
        jsApiList: [
               //所有要调用的 API 都要加到这个列表中
              "chooseImage"//从本地的相册、图库选择图片
        ]
    });

     以上的时间戳、随机数、签名一定要跟main方法中获取到的一致,否则会报invalid signature错误。

    另外,这个签名的有效时间为7200秒,也就是2个小时,因此当超过两个小时候,再访问也会报invalid signature错误。

    另外还有一个错误:invalid url domain

    这个跟生成签名时用的url有关系,官网的说法是:

    invalid url domain当前页面所在域名与使用的appid没有绑定,请确认正确填写绑定的域名,如果使用了端口号,则配置的绑定域名也要加上端口号(一个appid可以绑定三个有效域名)

    这个url必须是:“公众号设置---功能设置----JS接口安全域名”中绑定的三个域名之一

    若是以上的配置没有问题,且dubug也设置为了true,那么再访问的时候,就会出现一个config:ok,这就说明配置成功了。

     

  • 相关阅读:
    Atitit 集团与个人的完整入口列表 attilax的完整入口 1. 集团与个人的完整入口列表 1 2. 流量入口概念 2 3. 流量入口的历史与发展 2 1.集团与个人的完整入口列表
    atitit 每季度日程表 每季度流程 v3 qaf.docx Ver history V2 add diary cyar data 3 cate V3 fix detail 3cate ,
    Atitit react 详细使用总结 绑定列表显示 attilax总结 1. 前言 1 1.1. 资料数量在百度内的数量对比 1 1.2. 版本16 v15.6.1 1 1.3. 引入js 2
    Atitit r2017 r3 doc list on home ntpc.docx
    Atitit r2017 ra doc list on home ntpc.docx
    Atiitt attilax掌握的前后技术放在简历里面.docx
    Atitit q2016 qa doc list on home ntpc.docx
    Atitit r7 doc list on home ntpc.docx 驱动器 D 中的卷是 p2soft 卷的序列号是 9AD0D3C8 D:\ati\r2017 v3 r01\
    Atitit 可移植性之道attilax著
    Atitit q2016 q5 doc list on home ntpc.docx
  • 原文地址:https://www.cnblogs.com/xianyk/p/9992996.html
Copyright © 2011-2022 走看看