最近了解下基于 Token 的身份验证,跟大伙分享下。不少大型网站也都在用,好比 Facebook,Twitter,Google+,Github 等等,比起传统的身份验证方法,Token 扩展性更强,也更安全点,很是适合用在 Web 应用或者移动应用上。Token 的中文有人翻译成 “令牌”,我以为挺好,意思就是,你拿着这个令牌,才能过一些关卡。javascript
HTTP 是一种没有状态的协议,也就是它并不知道是谁是访问应用。这里咱们把用户当作是客户端,客户端使用用户名还有密码经过了身份验证,不过下回这个客户端再发送请求时候,还得再验证一下。php
解决的方法就是,当用户请求登陆的时候,若是没有问题,咱们在服务端生成一条记录,这个记录里能够说明一下登陆的用户是谁,而后把这条记录的 ID 号发送给客户端,客户端收到之后把这个 ID 号存储在 Cookie 里,下次这个用户再向服务端发送请求的时候,能够带着这个 Cookie ,这样服务端会验证一个这个 Cookie 里的信息,看看能不能在服务端这里找到对应的记录,若是能够,说明用户已经经过了身份验证,就把用户请求的数据返回给客户端。css
上面说的就是 Session,咱们须要在服务端存储为登陆的用户生成的 Session ,这些 Session 可能会存储在内存,磁盘,或者数据库里。咱们可能须要在服务端按期的去清理过时的 Session 。java
实施 Token 验证的方法挺多的,还有一些标准方法,好比 JWT,读做:jot ,表示:JSON Web Tokens 。JWT 标准的 Token 有三个部分:git
中间用点分隔开,而且都会使用 Base64 编码,因此真正的 Token 看起来像这样:github
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
header 部分主要是两部份内容,一个是 Token 的类型,另外一个是使用的算法,好比下面类型就是 JWT,使用的算法是 HS256。web
{
"typ": "JWT", "alg": "HS256" }
上面的内容要用 Base64 的形式编码一下,因此就变成这样:算法
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload 里面是 Token 的具体内容,这些内容里面有一些是标准字段,你也能够添加其它须要的内容。下面是标准字段:数据库
好比下面这个 Payload ,用到了 iss 发行人,还有 exp 过时时间。另外还有两个自定义的字段,一个是 name ,还有一个是 admin 。json
{
"iss": "ninghao.net", "exp": "1438955445", "name": "wanghao", "admin": true }
使用 Base64 编码之后就变成了这个样子:
eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ
JWT 的最后一部分是 Signature ,这部份内容有三个部分,先是用 Base64 编码的 header.payload ,再用加密算法加密一下,加密的时候要放进去一个 Secret ,这个至关因而一个密码,这个密码秘密地存储在服务端。
var encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload); HMACSHA256(encodedString, 'secret');
处理完成之后看起来像这样:
SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
最后这个在服务端生成而且要发送给客户端的 Token 看起来像这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
客户端收到这个 Token 之后把它存储下来,下回向服务端发送请求的时候就带着这个 Token 。服务端收到这个 Token ,而后进行验证,经过之后就会返回给客户端想要的资源。
参考:http://blog.csdn.net/sum_rain/article/details/37085771
Token,就是令牌,最大的特色就是随机性,不可预测。通常黑客或软件没法猜想出来。
那么,Token有什么做用?又是什么原理呢?
Token通常用在两个地方:
二者在原理上都是经过session token来实现的。当客户端请求页面时,服务器会生成一个随机数Token,而且将Token放置到session当中,而后将Token发给客户端(通常经过构造hidden表单)。下次客户端提交请求时,Token会随着表单一块儿提交到服务器端。
而后,若是应用于“anti csrf攻击”,则服务器端会对Token值进行验证,判断是否和session中的Token值相等,若相等,则能够证实请求有效,不是伪造的。
不过,若是应用于“防止表单重复提交”,服务器端第一次验证相同事后,会将session中的Token值更新下,若用户重复提交,第二次的验证判断将失败,由于用户提交的表单中的Token没变,但服务器端session中Token已经改变了。
上面的session应用相对安全,但也叫繁琐,同时当多页面多请求时,必须采用多Token同时生成的方法,这样占用更多资源,执行效率会下降。所以,也可用cookie存储验证信息的方法来代替session Token。好比,应对“重复提交”时,当第一次提交后便把已经提交的信息写到cookie中,当第二次提交时,因为cookie已经有提交记录,所以第二次提交会失败。
不过,cookie存储有个致命弱点,若是cookie被劫持(xss攻击很容易获得用户cookie),那么又一次gameover。黑客将直接实现csrf攻击。
因此,安全和高效相对的。具体问题具体对待吧。
此外,要避免“加token但不进行校验”的状况,在session中增长了token,但服务端没有对token进行验证,根本起不到防范的做用。
还需注意的是,对数据库有改动的增删改操做,须要加token验证,对于查询操做,必定不要加token,防止攻击者经过查询操做获取token进行csrf攻击。但并非这样攻击者就没法得到token,只是增大攻击成本而已。