Json Web Token(JWT)

发布于 2020-07-14 19:24:11   阅读量 54  点赞 0  

一、身份认证

 常见的服务器端身份认证机制有两种,分别为:

1.基于 session 的认证机制

 HTTP 是一种无状态的协议,这意味着若无登录态维持机制,则每次请求时都需要提交用户名与密码进行身份验证,而 session 机制就是用于在服务器端记录用户的登录状态。

 session 是一串在服务器生成的字符串,用以唯一地标识一个用户。第一次身份验证后,服务器生成一串字符串并将字符串保存在服务端,同时将该字符串写入返回的响应头(Cookie字段)。浏览器在收到字符串后,将该字符串保存为 Cookie。同一个用户(浏览器)再次访问服务器时,浏览器会在请求中自动添加 Cookie 以标识当前用户的身份,服务器收到请求后会与先前保存的字符串进行核验,确认用户的身份,以此来代替先前的用户名密码的认证方式。

session 认证的弊端
  • 增加开销:由于 session 都是保存在服务端内存中的,随着认证用户的增加,服务端的开销会明显增大。

  • 拓展性差:用户的认证记录被保存在数据库/内存中,这对于分布式的应用来说,增加了应用的拓展难度。

  • CSRF攻击:因为是基于 Cookie 来进行用户识别的,故容易受到跨站请求伪造的攻击。



2.基于 token 的鉴权机制

 基于 token 的鉴权机制是无状态的,它无需在服务器端保存用户的认证信息或会话信息,这意味着应用无需考虑用户在哪一台服务器登录了,为应用拓展提供了便利:

 JWT(全称Json Web Token)是一个规范,用于在用户与服务器之间传递可靠信息JTW官网。服务器端在初次验明用户的身份后,会生成带有签名的 Json 对象并将它返回客户端,客户端收到这个 Json 对象后存储起来。在之后的请求中,客户端将该 Json 对象连通请求一并发送至服务器,服务器通过这个 Json 对象标识用户。


token 的优点

 只需在服务器端记录 secret 密钥,而无需保存任意会话信息。每个用户的身份,都是通过对 token 的计算实时获取的,即将空间开销转换为时间(算力)开销。



二、JWT 结构

 JWT 是由三段字符串与两个.组成,这三段字符串按顺序依次为:

1.头部(header)

 头部是元数据,其是一个 Json 对象,描述了诸如签名使用的算法、令牌类型等信息。例如:

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

 上述头部alg属性指明了签名算法是 HS256 算法,即 JWT 的默认加密算法;typ表示令牌类型,这里就是 JWT。


2.载荷(payload)

 荷载是 JWT 的主体,同样是 Json 对象,用于包含相关声明。荷载包含三个部分:

① 标准注册声明

 预定义的声明,即标准规定的字段,并不强制使用,但一般推荐使用。它们有:

  1. iss:JWT 的签发者/发行人

  2. sub:该 JWT 面向的用户

  3. aud:接收方

  4. exp:JWT 的过期时间,必须大于签发时间

  5. nbf:JWT 的生效时间,在这个时间之前该 token 都是无效的

  6. iat:JWT 的签发时间

  7. jti:JWT 唯一身份标识,主要用来作为一次性 toekn,从而避免重放攻击


② 公共声明

 公共声明可以添加任何信息,一般添加用户的相关信息或业务信息。不建议添加敏感信息,因为该部分在客户端可解密。

③ 私有声明

 私有声明是服务器端与客户端共同定义的声明,同样不建议在这里添加敏感信息,因为 base64 是对称解密的,意味着该部分信息可以归类为明文信息。

下面是一个有效荷载的例子:

{
    "iss": "www.wjiaman.fun",
    "sub": "1234567890",
    "name": "John Doe",
    "admin": true
}

 对其进行加密,即可得到 JWT 的第 2 部分。



3.签名(signature)

 JWT 的第3部分是一个签证信息,该签证信息由 3 个部分组成:

  1. header(base64加密后)

  2. payload(base64加密后)

  3. secret

 首先,需要指定一个密钥secret,这个密钥只有服务器知道,用来进行 jwt 的签发与验证,它是服务端的私钥,不应泄露。只要知道了这个secret,就能自行签发 token。

 然后,使用 header 中指定的签名算法,用 secret 进行加盐加密 header.payload,产生签证(其中 header 与 payload 都是加密后的字符串)。

// javascript
let encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
let signature = HMACSHA256(encodedString, 'secret');

 计算出签名后,将 Header、Payload、Signature 用.组合起来后,就可以返回给用户。



三、客户端处理 JWT

 客户端收到服务器返回的 token 后,可以存储在 Cookie 里,也可以存储在 localStorage 中。

 此后,客户端每次与服务器通信,都要带上这个 token。若将这个 token 放在 Cookie 中,则浏览器将自动发送,但这样的缺点是不能跨域。于是更好的选择是放在 HTTP 请求头信息中的某个字段中(如Authorization)。

 另一种做法是,跨域请求时,token 就放在 POST 请求所提交的数据里。



四、JWT 的几个特点

  1. 由于 payload 部分的存在,故 JWT 可以在自身存储一些业务逻辑的非敏感数据。

  2. JWT 是不加密的,不应在 payload 中放置任何敏感数据(payload 是唯一可以放置自定义数据的部分),客户端能够解密 payload 中的所有信息。

  3. JWT 中唯一具有辨识作用的部分为 signature,服务器端通过 signature 计算结果的正确性来判断 payload 中信息(即用户信息)的正确性,从而确保 payload 中的信息没有被修改过。

  4. JWT 默认是不加密的,但也可以加密。在生成原始 token 后,可以用密钥再加密一次。

  5. JWT 在不加密的情况下,不能将敏感数据写入 JWT。

  6. JWT 不仅可以用于认证,还能用于交换信息。有效地使用 JWT,能够降低服务器查询数据库的次数。

  7. JWT 最大的缺点在于,由于服务器不保存任何状态信息,因此无法在使用过程中废除某个 token,使其失效,或更改某个 token 的权限。也即是说,一旦 JWT 一签发,在到期之前始终有效,除非服务器部署额外的逻辑。

  8. JWT 本身包含认证信息,一旦泄露,任何人都将获得对应令牌的所有权限。为了减少盗用,JWT 的有效期应相应短。且不应使用 HTTP 协议明码传输,尽量使用 HTTPS 协议进行传输。


Last Modified : 2020-09-24 14:50:52