深入理解Token
Token解决的问题
1.Token完全由应用管理,所以它可以避开同源策略.
2.Token可以避免CSRF攻击(跨域请求仿造).
3.Token可以是无状态的,可以在多个服务间共享.
Token是在服务端产生的,如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么服务端会反返回Token给前端,前端可以在每次请求的时候带上Token证明自己的合法地位,如果这个Token在服务端持久化(比如存入数据库),那它就是一个永久的身份令牌.
基于Token的身份验证过程如下:
1.用户通过用户名和密码发送请求请求登录
2.程序验证用户名和密码
3.创建一个签名的Token返回给客户端
4.客户端每次发送请求且携带Token
5.服务端验证Token
6.返回状态码
token应该在HTTP的头部发送从而保证了Http请求无状态,我们同样通过设置服务器属性"Access-Control-Allow-Origin",让服务器能接受到来自所有域的请求,主要的是在ACAO头部标明(designnating)时,不得带有像http认证,客户端ssl证书和cookies的证书.
AccessToken的默认存活时间是一个月,RefereshToken默认的存活时间是两个月,所谓的长期有效是用refereshtoken不断刷新获取新的.
因为Token有存活时间,所以过期如何处理?
1.过期了,就该要求用户重新登录.
2.可以设计一些复杂的机制,比如Referesh Token每次使用的时候,都更新他的过期时间.思路:查到与他的创建时间与当前时间相比,已经超过非常长的时间(自定义迭代的时间).这等于是在相当长一段时间内允许Referesh Token自动续费.
到目前为止,Token 都是有状态的,即在服务端需要保存并记录相关属性。那说好的无状态呢,怎么实现?
如果我们把所有状态信息都附加到Token上,服务器就可以不保存,但是服务端仍然需要认证Token有效,不过只要服务端能确认是自己签发的Token,而且信息未被改动过,那就可以认为Token有效—“签名”,可以做此保证.平常常说的签名都存在一方签发,另一方验证的情况,所以要是使用非对称的加密算法,但是在这里签发的验证的都是同一方,所以我么就可以使用对称的加密算法,而且对称加密算法比非对称加密算法要快的多(十倍左右)
对称加密算法除了加密,还带有还原加密内容的功能,而这一功能在对token签名时没有必要,既然不需要解密,就采用散列算法会更快,eg:HMAC
在使用无状态Token的时候在服务端会有一些变化,服务端虽然不保存有效的Token了,却需要保存未到期却已经注销的Token,如果一个Token未到期就被用户主动注销了,那么服务器需要保存这个被注销的Token,以便下次收到使用这个仍在有效期内的Token时判断其无效.
前端可以做控制,一旦注销就丢掉本地保存的Token和RefereshToken,基于这样的约定,服务器拿到的Token就一定是没有注销的.
使用无状态的Token的时候,有两点需要注意:
1.Referesh Token有效时间较长,所以它应该在服务器端有状态,以增强安全性,确保用户注销时可控.
2.应该考虑使用二次认证来增强敏感操作的安全性.
上面说的是认证服务和业务服务集成在一起的情况.如果是分离的情况呢?
分离认证服务
当Token无状态之后,单点登录就变得容易了,前端拿到一个有效的Token,他就可以在任何同一体系的服务上认证通过------------只要他们使用同样的秘钥和算法来认证Token的有效性.
当然,如果 Token 过期了,前端仍然需要去认证服务更新 Token:
虽然认证和业务分离了,实际即并没产生多大的差异。当然,这是建立在认证服务器信任业务服务器的前提下,因为认证服务器产生 Token 的密钥和业务服务器认证 Token 的密钥和算法相同。换句话说,业务服务器同样可以创建有效的 Token。