[微信]微信JS-SDK权限签名生成及验证


在使用微信的分享、图片等众多功能时,通常需要在config接口注入权限验证配置,而配置里有需要我们的权限签名,这里简单说一下权限签名的生成和验证

一、获取access_token

获取access_token需要两个东西,appID和appsecret,测试账号在此申请即用
在这里插入图片描述
测试账号的access_token每天做多获取2000次,最好是缓存起来,避免获取次数过多达到上限,申请测试账号之后,拿到appID和appsecret访问下列地址即可获取

https请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

获取access_token代码:

public synchronized String getAccessToken() {
        Object redisToken = redisTemplate.opsForValue().get("accessToken");
        if (redisToken == null) {
            String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=" + "client_credential"
                    + "&appid=" + appId + "&secret=" + appSecret;

            // 获取accessToken
            String accessTokenBody = cn.hutool.http.HttpUtil.get(accessTokenUrl);

            log.info("获取accessToken{}", accessTokenBody);

            com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(accessTokenBody);
            String accessToken = null;
            try {
                accessToken = (String) jsonObject.get("access_token");
                log.info("accessToken:{}", accessToken);
            } catch (Exception e) {
                log.error("获取accessToken异常");
            }
            // 存储一个小时
            redisTemplate.opsForValue().set("accessToken", accessToken, Constant.GenericNumber.NUMBER_ONE, TimeUnit.HOURS);
            return accessToken;
        } else {
            return redisToken.toString();
        }
    }

二、获取jsapi_ticket

使用第一步获取的access_token访问下述地址获取

采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

这一步也是需要进行缓存的,具体代码如下

private synchronized String getTicket(String accessToken) {

        Object jsapiTicket = redisTemplate.opsForValue().get("jsapiTicket");

        if (jsapiTicket == null) {
            String getTicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken
                    + "&type=jsapi";

            // 获取getTicketResult
            String getTicketResult = cn.hutool.http.HttpUtil.get(getTicketUrl);
            JSONObject ticketResultObject = JSONObject.parseObject(getTicketResult);

            String ticket = null;
            try {
                ticket = (String) ticketResultObject.get("ticket");
                log.info("ticket:{}", ticket);
            } catch (Exception e) {
                log.error("获取ticket异常");
            }

            // 缓存中的accessToken可能不是最新的,导致获取ticket失败
            // 清除redis缓存的accessToken重新获取 不使用递归避免其他原因获取失败而重复调用
            if (ticket == null) {
                redisTemplate.delete("accessToken");
                return getTicket(accessToken);
            }
            return ticket;

        } else {
            return jsapiTicket.toString();
        }

    }

三、拼接参数,SHA-1加密获取签名

签名生成规则如下:

参与签名的字段包括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

注意!注意!注意!
JAVA获取的时间戳是到毫秒级的,但是这里的时间戳是到秒的,需要换算之后才可以,生成之后的键值对一共是四组,不能有半组存在,尤其是开头的 “jsapi_ticket= ” 一定要有

SHA-1加密工具类:

private String encryptSHA(String signStr) {
        StringBuffer hexValue = new StringBuffer();
        MessageDigest sha = null;
        try {
            sha = MessageDigest.getInstance("SHA-1");
            byte[] byteArray = signStr.getBytes("UTF-8");
            byte[] md5Bytes = sha.digest(byteArray);
            for (int i = 0; i < md5Bytes.length; i++) {
                int val = ((int) md5Bytes[i]) & 0xff;
                if (val < 16) {
                    hexValue.append("0");
                }
                hexValue.append(Integer.toHexString(val));
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }

        return hexValue.toString();
    }

获取签名代码:

public cn.hutool.json.JSONObject createJsapiTicket(String url) {
        String accessToken = getAccessToken();
        String ticket = getTicket(accessToken);
        long timestamp = System.currentTimeMillis() / 1000;
        String noncestr = "letsschool";

        String signStr = new StringBuilder("jsapi_ticket=")
                .append(ticket)
                .append("&noncestr=")
                .append(noncestr)
                .append("&timestamp=")
                .append(timestamp)
                .append("&url=")
                .append(url)
                .toString();

        log.info("signStr:{}", signStr);

        String signature = encryptSHA(signStr);
        cn.hutool.json.JSONObject returnJson = JSONUtil.createObj();
        returnJson.put("timestamp", timestamp);
        returnJson.put("ticket", ticket);
        returnJson.put("noncestr", noncestr);
        returnJson.put("signature", signature);
        returnJson.put("appId", appId);

        return returnJson;
    }

四、验证签名

访问此地址,出现如下界面,输入参数生成签名,对比一致即可
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦及海深@无

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值