微信公众平台的TOKEN安全验证
来源:互联网 发布:广电网络和移动哪个好 编辑:程序博客网 时间:2024/05/07 19:36
本文目标:学习一种比较安全的服务器间互相验证身份的方式。
问题:开发微信公众平台接口,开发者的服务器为了确保请求是否来自微信服务器,应该如何去做?
1) 在微信管理页面上填写URL和TOKEN,开发者服务器上也记录同样的TOKEN。
2) 微信服务器发送HTTP请求,附带上参数(注意TOKEN是不会被传输的)
参数 描述signature微信加密签名timestamp时间戳nonce随机数echostr随机字符串
其中signature值通过如下摘要运算得出:
1. 将token、timestamp、nonce三个参数进行字典序排序2. 将三个参数字符串拼接成一个字符串进行sha1加密(这个加密是不可逆的),并将结果的byte[]转换为16进制字符串
3) 开发者服务器接收到signature,timestamp,nonce,echostr参数,跟服务器做同样的摘要运算,得到预期的一个signatrue,然后对比微信服务器发送过来的signature参数,如果相同,证明双方的TOKEN是一致的,开发者服务器确实接收到了来自微信服务器的请求,开发者服务器最后返回echostr,以告诉微信服务器接入成功。具体的开发者服务器校验逻辑代码如下显示。
- package message;
- import java.security.*;
- import java.util.Arrays;
- /***
- * 微信消息接口认证token摘要类
- *
- * 这个摘要类实现为单例,校验一个签名是否合法的例子如下
- * <pre>
- * WeixinMessageDigest wxDigest = WeixinMessageDigest.getInstance();
- * boolean bValid = wxDigest.validate(signature, timestamp, nonce);
- * </pre>
- *
- *
- * @author liguocai
- */
- public final class WeixinMessageDigest {
- /**
- * 单例持有类
- * @author liguocai
- *
- */
- private static class SingletonHolder{
- static final WeixinMessageDigest INSTANCE = new WeixinMessageDigest();
- }
- /**
- * 获取单例
- * @return
- */
- public static WeixinMessageDigest getInstance() {
- return SingletonHolder.INSTANCE;
- }
- private MessageDigest digest;
- private WeixinMessageDigest() {
- try {
- digest = MessageDigest.getInstance("SHA-1");
- } catch(Exception e) {
- throw new InternalError("init MessageDigest error:" + e.getMessage());
- }
- }
- /**
- * 将字节数组转换成16进制字符串
- * @param b
- * @return
- */
- private static String byte2hex(byte[] b) {
- StringBuilder sbDes = new StringBuilder();
- String tmp = null;
- for (int i = 0; i < b.length; i++) {
- tmp = (Integer.toHexString(b[i] & 0xFF));
- if (tmp.length() == 1) {
- sbDes.append("0");
- }
- sbDes.append(tmp);
- }
- return sbDes.toString();
- }
- private String encrypt(String strSrc) {
- String strDes = null;
- byte[] bt = strSrc.getBytes();
- digest.update(bt);
- strDes = byte2hex(digest.digest());
- return strDes;
- }
- /**
- * 校验请求的签名是否合法
- *
- * 加密/校验流程:
- * 1. 将token、timestamp、nonce三个参数进行字典序排序
- * 2. 将三个参数字符串拼接成一个字符串进行sha1加密
- * 3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
- * @param signature
- * @param timestamp
- * @param nonce
- * @return
- */
- public boolean validate(String signature, String timestamp, String nonce){
- //1. 将token、timestamp、nonce三个参数进行字典序排序
- String token = getToken();
- String[] arrTmp = { token, timestamp, nonce };
- Arrays.sort(arrTmp);
- StringBuffer sb = new StringBuffer();
- //2.将三个参数字符串拼接成一个字符串进行sha1加密
- for (int i = 0; i < arrTmp.length; i++) {
- sb.append(arrTmp[i]);
- }
- String expectedSignature = encrypt(sb.toString());
- //3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
- if(expectedSignature.equals(signature)){
- return true;
- }
- return false;
- }
- private String getToken(){
- return "111111";
- }
- public static void main(String[] args) {
- String signature="f86944503c10e7caefe35d6bc19a67e6e8d0e564";//加密需要验证的签名
- String timestamp="1371608072";//时间戳
- String nonce="1372170854";//随机数
- WeixinMessageDigest wxDigest = WeixinMessageDigest.getInstance();
- boolean bValid = wxDigest.validate(signature, timestamp, nonce);
- if (bValid) {
- System.out.println("token 验证成功!");
- }else {
- System.out.println("token 验证失败!");
- }
- }
- }
4) 这个摘要对比的技术,同样适用于单点登录、服务期间互相调用的身份验证,前提是每台服务器都持有相同的TOKEN。此外,有些细节可以优化,例如通过timestamp对签名做超时的处理,超时的签名默认不通过;请求的参数可以加上IP, USERID等额外信息;返回的echostr可以再次与TOKEN做摘要,可以使微信服务器确保接受来自开发者服务器的响应,但是微信服务器没有这么做,也许它本身已经做了足够安全控制。
微信消息接口文档:
http://mp.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3%E6%8C%87%E5%8D%97
- 微信公众平台的TOKEN安全验证
- 微信平台的token安全验证
- jsp 微信公众平台 token验证
- 微信公众平台Token验证失败
- jsp 微信公众平台 token验证
- 微信公众平台Token验证
- 微信公众平台Token验证失败问题的解决
- 微信公众平台开发(1)验证TOKEN源码
- 微信公众平台开发——token验证失败
- 微信公众平台开发者中心配置--token验证失败
- node.js微信公众平台开发之Token验证
- 微信公众平台你的服务器没有正确响应Token验证的解决方法
- 微信公众平台你的服务器没有正确响应Token验证的解决方法
- 基于PHP的微信公众平台开发(TOKEN验证,消息回复)
- 微信公众平台 开发者基本配置 token验证一直失败的时候
- 微信公众平台设置的URL和token
- Thinkphp5 微信公众号token验证不成功的原因
- 微信公众平台开发 ACCESS TOKEN
- Non-resolvable parent POM for **: Could not find artifact **
- 数据库创建计划任务
- 利用word2vec对关键词进行聚类
- ListView的扩展
- windows 平台 CONSOLE程序还是Windows程序
- 微信公众平台的TOKEN安全验证
- 存储过程创建多张表
- MATLAB 线性拟合 决定系数R2求解
- 我的幸运
- 关于ftp和http下载断点续传
- mysql 导入导出函数及存储过程
- Wordpress域名或主机更换后的内容自动更新
- Android系统中默认值的意义列表
- 最大正方形