Java分布式:JWT(JSON Web Tokens)

时间:2021-01-10 04:53:08

Java分布式:JWT(JSON Web Tokens) 

0、优势

  Session方式存储用户状态占用大量服务器内存。一般而言,大型应用还需要借助一些KV数据库和一系列缓存机制来实现Session的存储。而JWT方式将用户状态分散到了客户端中,可以明显减轻服务端的内存压力。除了用户id之外,还可以存储其他的和用户相关的信息,例如该用户是否是管理员、用户所在的分桶等。

 

1.原理

  JWT的原则是在服务器身份验证之后,将生成一个JSON对象并将其发送回用户,可能的返回JSON如下“:

{
    "UserName": "Chongchong",
    "Role": "Admin",
    "Expire": "2018-08-08 20:15:56"
}

  之后,每次用户与服务器通信时,客户在请求中发回JSON对象。服务器仅依赖于这个JSON对象来标识用户。为了防止用户篡改数据,服务器将在生成对象时添加签名服务器不保存任何会话数据,即服务器变为无状态,使其更容易扩展。

  Java分布式:JWT(JSON Web Tokens)

2.结构

  分为三部分,依次为JWT头、有效载荷、签名。最终效果是XXXX.YYYY.ZZZZ,即三部分的和,中间用小数点分割。

  Java分布式:JWT(JSON Web Tokens)

2.1JWT头

  Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常是下面的样子。

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

  上面代码中,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。最后,将上面的 JSON 对象使用 Base64URL 算法转成字符串。

2.2有效载荷

  Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据

{
    "sub": "1234567890",
    "name": "John Doe",
    "admin": true
}

  除了自定义外,也可以使用JWT 提供的7个官方字段。

  • iss (issuer):签发人
  • exp (expiration time):过期时间
  • sub (subject):主题
  • aud (audience):受众
  • nbf (Not Before):生效时间
  • iat (Issued At):签发时间
  • jti (JWT ID):编号

  这个 JSON 对象也要使用 Base64URL 算法转成字符串。

2.3签名

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

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

  计算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。

 2.4Base64URL 算法

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

3.使用方法

  客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。此后,客户端每次与服务器通信,都要带上这个 JWT。

  你可以把它放在 Cookie 里面自动发送,但是这样不能跨域。

  你也可以将其放在 HTTP 请求的头信息Authorization字段里面,如下

Authorization: Bearer <token>

  另一种做法是,跨域的时候,JWT 就放在 POST 请求的数据体里面。