Json Web Token (JWT)是一种跨域认证解决方案。
跨域认证
跨域的一般流程是下图中1.2.3 的方式。
- 客户端将用户名和密码 传到服务器,服务器验证通过后,将session中保存相关数据,并且返回给用户一个session_id,写入用户的 cookie 中。以后用户的每一次请求,都会将session_id 放入 cookie 中,带给服务器,服务器收到 session_id 后,将之前保存的数据找到,对比,以此确定用户身份。
A,B两家公司关联服务,用户只要第一次在一个网站上登录,再次访问另一个网站时就自动登录,如何实现?
上面的方法只能在一个服务端才能实现,两个服务端没有办法获取 session_id, 所以有两种方案解决:
-
session 数据持久化。
将session写入数据库或者别的持久层。在每个服务器收到请求后,都想吃就出让请求数据。
缺: 持久层不稳定,可能会挂 -
服务器不保存session 数据, 所有数据保存在客户端,每次请求都将 session数据发回服务器。JWT 就是一个很好的代表。
JWT 原理
服务器认证后,生成一个 json 对象,发给用户。
用户与服务器通信时,都要发挥这个json 对象 (服务器在生成这个对象时会加上签名,这个签名就保证了当用户传回数据时,服务器能够识别该数据)服务器不保存 session 数据了,变成了无状态的,易于实现扩展。
JWT 数据结构
JWT 分为三部分:
- Header (头部)
- Payload (负载)
- Signature (签名)
JWT 是一个很长的字符串, 没有换行,这三部分使用点 .
连接起来。
Header 和 Payload 使用 Base64URL 转成字符串。
-
Header 是一个 json 对象, 描述 JWT 的元数据。
{ "alg": "HS256", "typ": "JWT" }
alg 表示签名算法,默认是 HMACSHA256(HS256)
typ 表示这个令牌(token)的类型。 -
Payload 是一个 json 对象,用来存放实际需要传递的数据。
官方字段有7个: -
iss (issuer):签发人
-
exp (expiration time):过期时间
-
sub (subject):主题
-
aud (audience):受众
-
nbf (Not Before):生效时间
-
iat (Issued At):签发时间
-
jti (JWT ID):编号
也可以定义私有字段。
注: JWT 默认不加密, 任何人都可以读到用 Base64URL 转成的字符串。
- Signature 对前两部分签名,防止篡改数据。
这部分需要指定密钥(screat),只用服务器知道的密钥。 使用 Header 中指定的签名算法(默认HS256)按照下面方式产生签名:
算出签名后,将Header, Payload,Signature 用点分隔拼成一个字符串,就可以返回给用户。HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), screat )
JWT 使用方式
客户端收到服务器返回的 JWT, 可以存在 Cookie 里 或者 localStorage 中。 客户端每次与服务器通信就要带上 JWT, 可以将它放在 cookie 中自动发送, 但不能跨域,所以放在 HTTP 请求头信息 Authorization 字段里。
Authorization: Bearer <token>
另一种做法: 跨域的时候,JWT 放在 POST 请求的数据体里。
参考文章:
http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html