学习笔记 - JWT

JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案。

1. 一般的认证流程

  1. 用户向服务器发送用户名和密码
  2. 服务器通过验证后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等
  3. 服务端向用户返回一个session_id,写入用户的Cookie
  4. 用户随后的每一次请求,都会通过Cookie,将session_id传回服务器
  5. 服务器收到session_id,找到前期保存的数据,由此得知用户的身份

    这种模式在单机情况下没有问题。如果是服务集群,或者是跨域的服务导向架构,就要求session数据共享,每台服务器都能都读取到session。例如:A 网站和 B 网站是同一家公司的关联服务。要求用户只要在其中一个网站登录,再访问另一个网站就自动登录。
    一种解决方案就是:服务器索性不保存 session数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT 就是这种方案的一个代表。

2. JWT原理

  1. 服务器认证以后,生成一个JSON对象,发回给用户
  2. 之后用户与服务端通信的时候,都要发回这个 JSON对象
  3. 服务器完全只靠这个对象认定用户身份
  4. 为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名
  5. 这样服务器就不保存任何session数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展

3. JWT例子

  1. 它是一个很长的字符串,中间用点 . 分隔成三个部分
  2. 包括了头部Header、负载Payload、签名Signature。即Header.Payload.Signature
  3. 以下是一个例子,可在JWT解析网址下解析并得到信息
    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
    

3.1. Header

  1. 一个JSON对象,描述JWT的元数据 ,格式是:{"alg": "HS256","typ": "JWT"}
  2. alg属性表示签名的算法(algorithm),默认是HMAC SHA256(HS256)
  3. typ属性表示这个令牌的类型,JWT令牌统一写为JWT
  4. 最后,将上面的 JSON 对象使用Base64URL算法转成字符串

3.2. Payload

  1. 也是一个JSON对象,用来存放实际需要传递的数据
  2. JWT 规定了7个官方字段,供选用:
    字段 解释 备注
    iss issuer 签发人
    exp expiration time 过期时间
    sub subject 主题
    aud audience 受众
    nbf Not Before 生效时间
    iat Issued At 签发时间
    jti JWT ID 编号
  3. 除了官方字段,还能自定义私有字段{"sub":"1234567890","name": "John Doe","admin": true}
  4. 注意,JWT默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分
  5. 这个JSON对象也要使用Base64URL算法转成字符串

3.3. Signature

  1. 是对HeaderPayload这两部分的签名,防止数据篡改
  2. 首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户
  3. 然后,使用Header里面指定的签名算法(默认是HMAC SHA256),按照公式产生签名
    HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )
    

3.4. Base64URL

  1. 前面提到的Header 和 Payload串型化的算法是 Base64URL
  2. 这个算法跟 Base64 算法基本类似,但有一些小的不同
  3. JWT 作为一个令牌,有些场合可能会放到URL(如 api.example.com/?token=xxx)
  4. Base64 有三个字符+、/和=,在 URL里面有特殊含义
  5. 所以要被替换掉,= 被省略 + 替换成 - / 替换成 _ ,这就是 Base64URL 算法

4. JWT的使用

  1. 客户端收到服务器返回的 JWT,可以储存在 Cookie或localStorage
  2. 此后,客户端每次与服务器通信,都要带上这个JWT
  3. 可以放在Cookie里面自动发送,但是这样不能跨域
  4. 所以更好的做法是放在 HTTP请求的头信息Authorization字段里面Authorization: Bearer
  5. 另一种做法是跨域的时候,JWT 就放在 POST 请求的数据体里面

5. JWT特点

  1. 默认不加密,但可以在生成原始Token之后,再用密钥加密一次
  2. 不加密的情况下,不能将秘密数据写到JWT
  3. JWT不仅可以用于认证,也可以用于交换信息
  4. 有效使用JWT,可以降低服务器查询数据库的次数
  5. 由于服务器不保存session状态,因此无法在使用过程中废止某个token,或者更改token权限
  6. 即JWT一旦签发,在到期之前就会始终有效,除非服务器部署额外的逻辑(如Redis)
  7. JWT本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限
  8. 为了减少盗用,JWT的有效期应该设置得比较短
  9. 重要的权限,应该在使用时再次对用户做认证
  10. 为了减少盗用,JWT不应该使用HTTP协议明码传输,要使用HTTPS协议传输

6. 参考资料

  1. 阮一峰 - JSON Web Token 入门教程
  2. Introduction to JSON Web Tokens

你可能感兴趣的:(学习笔记 - JWT)