基于 Token 的身份验证

基于 Token 的身份验证

最近了解下基于Token的身份验证,跟大伙分享下。很多大型网站也都在用,比如Facebook,Twitter,Google+,Github等等,比起传统的身份验证方法,Token扩展性更强,也更安全点,非常适合用在Web应用或者移动应用上。Token的中文有人翻译成“令牌”,我觉得挺好,意思就是,你拿着这个令牌,才能过一些关卡。


传统身份验证的方法

HTTP是一种没有状态的协议,也就是它并不知道是谁是访问应用。这里我们把用户看成是客户端,客户端使用用户名还有密码通过了身份验证,不过下回这个客户端再发送请求时候,还得再验证一下。

解决的方法就是,当用户请求登录的时候,如果没有问题,我们在服务端生成一条记录,这个记录里可以说明一下登录的用户是谁,然后把这条记录的ID号发送给客户端,客户端收到以后把这个ID号存储在Cookie里,下次这个用户再向服务端发送请求的时候,可以带着这个Cookie,这样服务端会验证一个这个Cookie里的信息,看看能不能在服务端这里找到对应的记录,如果可以,说明用户已经通过了身份验证,就把用户请求的数据返回给客户端。

上面说的就是Session,我们需要在服务端存储为登录的用户生成的Session,这些Session可能会存储在内存,磁盘,或者数据库里。我们可能需要在服务端定期的去清理过期的Session。


基于 Token 的身份验证方法

使用基于Token的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:

    1)客户端使用用户名跟密码请求登录

    2)服务端收到请求,去验证用户名与密码

    3)验证成功后,服务端会签发一个Token,再把这个Token发送给客户端

    4)客户端收到Token以后可以把它存储起来,比如放在Cookie里或者Local Storage 里

    5)客户端每次向服务端请求资源的时候需要带着服务端签发的Token

    6)服务端收到请求,然后去验证客户端请求里面带着的Token,如果验证成功,就向客户端返回请求的数据


JWT

 实施Token验证的方法挺多的,还有一些标准方法,比如JWT,读作:jot,表示:JSONWeb Tokens。JWT标准的Token有三个部分:

    header

    payload

    signature

中间用点分隔开,并且都会使用Base64编码,所以真正的Token看起来像这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
Header

header部分主要是两部分内容,一个是Token的类型,另一个是使用的算法,比如下面类型就是JWT,使用的算法是HS256。

{
    "typ": "JWT",
    "alg": "HS256"
}
上面的内容要用Base64的形式编码一下,所以就变成这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload
Payload里面是Token的具体内容,这些内容里面有一些是标准字段,你也可以添加其它需要的内容。下面是标准字段:
    iss:Issuer,发行者
    sub:Subject,主题
    aud:Audience,观众
    exp:Expiration time,过期时间
    nbf:Not before
    iat:Issued at,发行时间
    jti:JWT ID
比如下面这个Payload,用到了iss发行人,还有exp过期时间。另外还有两个自定义的字段,一个是name,还有一个是admin。
{
    "iss": "ninghao.net",
    "exp": "1438955445",
    "name": "wanghao",
    "admin": true
}

使用Base64编码以后就变成了这个样子:

eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ
Signature

JWT的最后一部分是Signature,这部分内容有三个部分,先是用Base64编码的header.payload,再用加密算法加密一下,加密的时候要放进去一个Secret,这个相当于是一个密码,这个密码秘密地存储在服务端。

    header

    payload

    secret

var encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload); 
HMACSHA256(encodedString, 'secret');

处理完成以后看起来像这样:

SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc

最后这个在服务端生成并且要发送给客户端的Token看起来像这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc

客户端收到这个Token以后把它存储下来,下回向服务端发送请求的时候就带着这个Token。服务端收到这个Token,然后进行验证,通过以后就会返回给客户端想要的资源。

参考资料:https://ninghao.net/blog/2834

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值