2018-09-01
前言
前几天谈一个合作,写了份技术文档。对方看了之后抛出萌新三连:什么是token?怎么生成?有什么用?
本文简单介绍token,并介绍基于token的用户认证方案。
Token是什么
Token是一个身份凭证,有个很贴切的翻译叫“令牌”。发给你一个令牌,你在遇到关卡的时候出示令牌,证明自己的身份。
Token的概念广泛应用于许多领域。比如区块链中,比特币和以太坊的“代币”,形式也是token。本文具体讨论的是用于网站登录态的Token方案。
Access Token方案
注意,登录这一步的关键是验证用户身份,不一定是用户名/密码的登录接口,也可以是其他方式,只要保证token能安全颁发到客户端即可。可以参考我之前另一篇博客《Gitlab-CI实践》,token是直接复制粘贴的。
怎么生成Token
Token的要求:
无规律的字符串。
每个用户、每次获取都不同。
不重复。
生成方式:
最简单的实现方式,以当前时间戳作为盐,对用户ID进行MD5。
使用用散列加密算法。node.js可以用crypto.createHmac,PHP可以用openssl_random_pseudo_bytes或mcrypt_create_iv。
常用的框架一般都有生成token的函数,可以参考相关文档。
怎么使用Token
客户端收到Token之后需要妥善保管,不可轻易泄漏。如果客户端是网页,建议存在Cookie中,并设为HttpOnly。客户端发起Ajax请求的时候,需要带上Token,可以随cookie发送,也可以在作为Http header中的自定义参数。
服务器生成token时也需要妥善保存,一般存于数据库,与用户信息一一对应。验证token时,根据token反查对应的用户,再进行权限校验等。
Token的有效期
登录态不是永久的,肯定要有过期或者失效的机制。这通常服务端来实现过期机制的。
服务器在创建或更新token时,使用另一个字段存储这个token的过期时间。每次校验token的时候,只匹配有效期内的token。有效期的长短根据业务需求来定,也可以设计成每次业务请求时刷新过期时间,太久不进行业务请求就判断为token已经失效。如果想从服务端主动吊销已经颁发的token,也只需要修改过期时间就行了。
对于客户端来说,token只有“有效”和“失效”两种状态,如果发给服务器验证失败,那么说明本地存的token已经失效了,直接删掉,重新走登录流程去获取。如果使用cookie来储存token,cookie本身可以设置过期时间,可以参考我之前的博客《全面了解Cookie》。
还有另一类把过期时间存在客户端的方案,本文不做讨论,有兴趣可以参考我另一篇博客《Json Web Token》。
Token和Cookie的关系
Cookie只是token的储存和发送的方案之一。你也可以把token存到localStorage中,并使用自定义http header字段来发送给服务端。但这样做带来有严重的安全性问题:
localStorage无法设置HttpOnly、Domain和Path,XSS攻击可轻易窃取token;
Cookie会在每个请求中带上,包括图片和文件,服务器都能对其进行校验。但Token如果放在Http header中,一般只用在XMLHttpRequest中。
为了避免安全性问题,web应用推荐使用cookie来储存token。
Cookie仅限于浏览器上的web应用,仅限于http相关的协议,而token却不受此限制。只要能保证token储存和传递的安全性,它可以用在任何应用、任何协议上。
后记
本文介绍了Token的基础知识和Access Token方案。下篇博客将介绍Json Web Token(JWT)相关内容。
本文未经许可禁止转载,如需转载请联系 JAY@oonne.com