appkey 和 secret key & token

来源:互联网 发布:mac os x 10.6.8 编辑:程序博客网 时间:2024/04/30 16:12
appkey 和 secret key相当于当前账户的另外一套账号和密码机制. 当然, 仅仅是在API调用的范围内适用.
1.生成方式可以自己定义, appkey保证不重复就行. secret key保证不容易被穷举, 生成算法也不能被轻易猜到. salt是一个不错的方式.
2.我们假定 appkey = 'AK' secret key = 'BK' 当前时间为 'T' 随机值 'R'我们需要在客户端生成一个verify code 假设公式是 md5('BK_T_R'), 我们称他为VC.每次调用API的时候, 会把AK, T, R, VC传回服务器端.再服务器端验证VC 是否等于 md5('BK_T_R'), 即是否符合算法要求.这套算法有个问题, 如果AK, T, R不变, 那么VC就肯定是固定的. 客户端有伪造的可能.服务器端可以做如下策略, 比如时间抛弃, 客户端时间和服务器时间相差较大, 比如一个小时以上, 那么直接抛弃这次请求. 并且记录下当前AK最近提交的T_R, 保证这对组合应该是在当前AK范围内是唯一值. 如果发现有第二次调用, 直接抛弃.只要VC的算法稍微靠谱点, 相信这套机制还是有一定的安全性了.
3.其他作用比如你提到的统计, 这种在任何系统里面都可以实现, 不能算是这种的独有的.
我来说几点.
a.相较在客户端存储原账号密码, 可以保证原账号密码安全性. 毕竟这套机制只是在API范围内适用.
b.可抛弃性,secret可以经常更新达到更好的安全性.
c.可以直接拒绝某一个AK, 而不影响当前账户的其他AK.



token的微信:使用Token是一个用户自定义的任意字符串。在成功提交了开发者自定义的这个字符串之后,Token的值会保存到微信后台。只有服务器和微信后台知道这个字符串,也就是说只有微信后台和公众账号服务器知道这个字符串。于是Token就成了这两台服务器之间的密钥,它可以让公众账号服务器确认请求是来自微信后台还是恶意的第三方。

以下是Token验证的具体过程。

1)微信后台在向公众账号服务器发送数据的时候,会额外带上4个参数:timestamp、signature、nonce、echostr,如表3-1所示。其中timestamp是时间戳,nonce是一个随机数,signature是对timestamp、nonce和Token进行SHA1加密后的字符串。SHA1的加密过程是不可逆的,即不能通过timestamp、signature和nonce计算出Token是什么。


2)在公众账号服务器收到timestamp、signature和nonce之后,同样对nonce、timestamp和Token使用SHA1加密算法,得到自己的签名,如果自己的签名和请求中的signatrue是一样的,那么说明请求是来自微信后台而不是恶意第三方。

注意 恶意的第三方有可能会截获微信后台发过来的timestamp、signature和nonce这三个参数,然后直接利用这个三个参数对公众账号服务器发起请求。按照上面的逻辑可以知道,服务器是无法判断出这是个恶意的请求的。这种攻击称为replay攻击。这种攻击方式的防御方法很简单:加上对timestamp的校验。在收到请求之后,将请求包中的timestamp与当前时间比较,如果误差大于一定的值,就可认为这个请求是恶意的。这里不能做相等的比较,因为数据在网络上传输需要时间,同时各个服务的本地时间也是有一些差异的。

微信服务器通过检验signature对请求进行校验(下面有校验方式)。若此次GET的Token验证可以通过,则表示该请求来自微信服务器,这时会原样返回echostr参数内容,表示接入生效,否则接入失败。

检验signature的PHP示例代码如下:
 

  1. private function checkSignature(){  
  2.     $signature = $_GET["signature"];  
  3.     $timestamp = $_GET["timestamp"];  
  4.     $nonce = $_GET["nonce"];  
  5.     $token = TOKEN;  
  6.     $tmpArr = array($token, $timestamp, $nonce);  
  7.     sort($tmpArr);  
  8.     $tmpStr = implode( $tmpArr );  
  9.     $tmpStr = sha1( $tmpStr );  
  10.     if( $tmpStr == $signature ){    return true;}  
  11.     else{return false;}  

token是个凭条,不过它比门票温柔多了,门票丢了重新花钱买,token丢了重新操作下认证一个就可以了,因此token丢失的代价是可以忍受的——前提是你别丢太频繁,要是让用户隔三差五就认证一次那就损失用户体验了。

基于这个出发点,如果你认为用数据库来保持token查询时间太长,会成为你系统的瓶颈或者隐患,可以放在内存当中。
比如memcached、redis,KV方式很适合你对token查询的需求。
这个不会太占内存,比如你的token是32位字符串,要是你的用户量在百万级或者千万级,那才多少内存。
要是数据量真的大到单机内存扛不住,或者觉得一宕机全丢风险大,只要这个token生成是足够均匀的,高低位切一下分到不同机器上就行,内存绝对不会是问题。

客户端方面这个除非你有一个非常安全的办法,比如操作系统提供的隐私数据存储,那token肯定会存在泄露的问题。比如我拿到你的手机,把你的token拷出来,在过期之前就都可以以你的身份在别的地方登录。
解决这个问题的一个简单办法
1、在存储的时候把token进行对称加密存储,用时解开。
2、将请求URL、时间戳、token三者进行合并加盐签名,服务端校验有效性。
这两种办法的出发点都是:窃取你存储的数据较为容易,而反汇编你的程序hack你的加密解密和签名算法是比较难的。然而其实说难也不难,所以终究是防君子不防小人的做法。话说加密存储一个你要是被人扒开客户端看也不会被喷明文存储……
方法1它拿到存储的密文解不开、方法2它不知道你的签名算法和盐,两者可以结合食用。
但是如果token被人拷走,他自然也能植入到自己的手机里面,那到时候他的手机也可以以你的身份来用着,这你就瞎了。
于是可以提供一个让用户可以主动expire一个过去的token类似的机制,在被盗的时候能远程止损。
<del>话说一个人连自己手机都保护不好还谈什么安全……</del>

在网络层面上token明文传输的话会非常的危险,所以建议一定要使用HTTPS,并且把token放在post body里。

OAuth: OAuth(开放授权)是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容。

QQ登录OAuth2.0:对于用户相关的OpenAPI(例如获取用户信息,动态同步,照片,日志,分享等),为了保护用户数据的安全和隐私,第三方网站访问用户数据前都需要显式的向用户征求授权。
QQ登录OAuth2.0采用OAuth2.0标准协议来进行用户身份验证和获取用户授权,相对于之前的OAuth1.0协议,其认证流程更简单和安全。

即server-side模式,是OAuth2.0认证的一种模式,又称Web Server Flow;
适用于需要从web server访问的应用,例如Web/wap网站。


其授权验证流程示意图如下(图片来源:OAuth2.0协议草案V21的4.1节 ) 



对于应用而言,需要进行两步:
1. 获取Authorization Code;
2. 通过Authorization Code获取Access Token




0 0