基于 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 ,表示:JSON Web Tokens 。JWT 标准的 Token 有三个部分:spa

  • header
  • payload
  • signature

中间用点分隔开,而且都会使用 Base64 编码,因此真正的 Token 看起来像这样:.net

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc

Header

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

{
  "typ": "JWT",
  "alg": "HS256"
}

上面的内容要用 Base64 的形式编码一下,因此就变成这样:内存

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Payload

Payload 里面是 Token 的具体内容,这些内容里面有一些是标准字段,你也能够添加其它须要的内容。下面是标准字段:ci

  • 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 ,而后进行验证,经过之后就会返回给客户端想要的资源。

相关文章
相关标签/搜索