微信平台的token安全验证(转)

标签: 微信 平台 token | 发表时间:2014-03-27 16:41 | 作者:yehlv
出处:http://www.iteye.com


本文目标:学习一种比较安全的服务器间互相验证身份的方式。



问题:开发微信公众平台接口,开发者的服务器为了确保请求是否来自微信服务器,应该如何去做?



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,以告诉微信服务器接入成功。具体的开发者服务器校验逻辑代码如下显示。




Java代码  收藏代码

    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


已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [微信 平台 token] 推荐:

微信平台的token安全验证(转)

- - 行业应用 - ITeye博客
本文目标:学习一种比较安全的服务器间互相验证身份的方式. 问题:开发微信公众平台接口,开发者的服务器为了确保请求是否来自微信服务器,应该如何去做. 1)  在微信管理页面上填写URL和TOKEN,开发者服务器上也记录同样的TOKEN. 2)  微信服务器发送HTTP请求,附带上参数(注意TOKEN是不会被传输的).

基于token的多平台身份认证架构设计 - 一点一滴的Beer - 博客园

- -
在存在账号体系的信息系统中,对身份的鉴定是非常重要的事情. 随着移动互联网时代到来,客户端的类型越来越多, 逐渐出现了  一个服务器,N个客户端的格局 . 不同的客户端产生了不同的用户使用场景,这些场景:. 综上所述,它们的身份认证方式也存在一定的区别. 本文将使用一定的篇幅对这些场景进行一些分析和梳理工作.

RSA的SecureID token数据被偷了?

- ripwu - 张志强的网络日志
博客 » 记事本 » 密码学 ». WSJ报道:RSA承认其数据被偷,4000万SecureID token需要被更新. 中国银行银行密钥用的就是RSA生产,就是下图这玩意儿,手里有这玩意儿的同学们要小心了(当然,如果你的账户里的钱没有6位数以上,也不用太担心,毕竟网银的安全性不全依赖于这个设备):.

什么是 JWT -- JSON WEB TOKEN - 简书

- -
Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准(. (RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景. JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密.

浅谈微信公众平台

- - 微博之博
过去的这个周末,应该大部分人都在家里调戏 微信公共 平台. 有人幸灾乐祸,有人稍作恐慌:芸芸众生相. 注册尝试了一个微信 公众平台,总结一句话:龙生龙,凤生凤. 以前曾经有人说中国的互联网,要么生要么死要么被腾讯. 企鹅家族优良的传统,势必不会放过 微博帝国的3亿用户群的潜在商业价值,所以这次爱起哄的企鹅家族,又一次决定露出起哄天性,悄悄的推出了微信公众平台.

微信公众平台开发(一)

- - BlogJava-首页技术区
  开始微信公众平台的开发,我们首先要了解微信平台可以帮助我们做哪些事情. 使用您的公众账号登陆http://mp.weixin.qq.com/,选择菜单--高级功能-开发模式--查看文档,即能看到微信公众平台目前所能开发的功能. 接受用户发送给您公众账号的消息. 需要特别说明的是,发送消息和回复消失是一个连贯的过程,只能在一个对话中完成.

微信公众平台接口开发

- - CSDN博客互联网推荐文章
随着微信公众平台的开放,微信营销推广也越发受到重视. 现在企业越来越注重求职者是否拥有“微信公众平台接口开发”的经验. 现在参考资料介绍下微信公众平台接口开发模式:. 首先你得有个微信公众平台账号,注册地址:http://mp.weixin.qq.com/. 开发者提交信息后,微信服务器将发送GET请求到填写的URL上,GET请求携带四个参数:.

微信公众平台开发入门

- - Web前端 - ITeye博客
在这篇微信公众平台开发教程中,我们假定你已经有了PHP语言程序、MySQL数据库、计算机网络通讯、及HTTP/XML/CSS/JS等基础. 我们将使用微信公众账号方倍工作室作为讲解的例子,二维码见底部. 本系列教程将引导你完成如下任务:. 我们使用SAE新浪云计算平台作为服务器资源,并且申请PHP环境+MySQL数据库作为程序运行环境.

微信公众平台:移动推送(Push)平台

- - 天涯海阁|Web2.0Share
之前曾经写过一个文章《 移动互联网的未来:基于情境/兴趣的推送》,至今我也觉得这个在未来会是有着巨大想想空间的移动生活方式. 之前其实也有不少初创企业在Push这个领域努力,不过效果却都不好,所以其实本质而言,要构建Push这样的平台,需要吸引大量的内容、媒体、品牌来提供Push内容,而对于内容、媒体、品牌而言,最在意的是这个平台有没有用户,而微信可能已经到了可以去构建这样一个信息推送平台的阶段.

微信企业号,微信平台再次拓展边界

- - 爱范儿 · Beats of Bits
波士顿大学管理学院副教授马歇尔·范·阿尔斯蒂尼(Marshall Van Alstyne)曾经提到产品公司和平台公司的不同定义(翻译来自 iWeekly 的仇烨):. 如果你生产价值,那么这就是一个典型的产品公司. 而现在有一些新的系统,价值是在公司之外创造的,这就是一个平台公司. 苹果可以在其应用商店中获得他人创意的 30% 收入.