什么是JWT?
JWT(JSON Web Token)是一种用于在各方之间安全地传输信息的紧凑、自包含的令牌格式。JWT是一种基于JSON的标准,定义了一种简洁的方式来表示请求方和提供方之间的验证信息。它通常用于Web应用的身份验证和授权。
基于Session的认证流程
web服务离不开用户认证。一般流程是下面这样。
Session存在的问题
- 多台服务器共享问题:如果系统部署在多台服务器上(例如在负载均衡的情况下),每台服务器都需要能够访问所有的session数据。这就要求这些服务器之间共享session信息。
第一种解决方案
session复制,在这种方法中,每当用户的session在某台服务器上创建或更新时,session数据都会被复制到集群中的其他服务器上。因此,无论用户的请求被负载转发到哪台服务器,这些服务器都可以访问相同的session数据
这样对服务器不太友好,每个人只需要保存自己的 session id,而服务器要保存所有人的 session id !如果访问服务器多了, 就得由成千上万,甚至几十万个。
第二种解决方案
就是使用服务器来存储session_id。这个想法是将所有的session数据集中存储在这台服务器中,所有服务器都去访问同一个存储位置来获取session数据。这样一来,避免了在不同服务器之间复制session数据的麻烦。
这样也存在一种问题,就是当这个session存储的服务器挂了所以session全部失效,必须全部重新登录
使用JWT
可以换种思路上,不一定需要进行存储session,而是在存在客户端存储,可是如果不保存这些 session id, 怎么验证客户端发给我的 session id 的确是我生成的呢,如果不去验证,我们都不知道他们是不是合法登录的用户。
JWT的结构
一个JWT通常由三部分组成:Header(头部)、Payload(负载)和Signature(签名),它们通过.分隔开来。
1. Header
Header通常包括两部分:令牌类型(即JWT)和所使用的签名算法(如HMAC SHA256或RSA)。Header的JSON形式如下:
{
"alg": "HS256",
"typ": "JWT"
}
将上述JSON数据进行Base64Url编码后,得到JWT的第一部分。
2. Payload
Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。
iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
还可以定义私有字段
{
"username": "mengyunzhi",
"name": "yunzhi",
"role": "admin"
}
JWT 默认是不加密的,任何人都可以读到,所以不要把敏感信息(password或重要的个人身份信息)放在这个部分。
这个 JSON 对象也要使用 Base64URL 算法转成字符串。
3. Signature
Signature 部分是对前两部分的签名,防止数据篡改。
首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJ1c2VybmFtZSI6Im1lbmd5dW56aGkiLCJuYW1lIjoieXVuemhpIiwicm9sZSI6ImFkbWluIn0.
Gecz5qFrimEVsxTIEvsgBvhEyyX2acr88YkT0ec-VGI
4. Base64URL
为什么P要使用Base64URL进行加密算法
JWT 作为一个令牌(token),有时候会放上在 URL。Base64 有三个字符+、/和=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_ 。这就是 Base64URL 算法。
www.mengyunzhi.com/?token=xxxx
JWT 的使用方式
客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。
此后,客户端每次与服务器通信,都要带上这个 JWT。一般是放在 HTTP 请求的头信息Authorization字段里面。
Authorization: Bearer <token>
总结
相比于传统的基于Session的身份验证方法,JWT具有以下几个优势:
无状态:JWT不需要在服务器端存储用户会话数据,令牌本身包含了所有必要的用户信息。
适用分布式:由于JWT在客户端持有,而不依赖于服务器进行session存储,因此在多个服务器或微服务之间传递用户身份信息时,JWT更为方便。
减少服务器负载:服务器不需要为每个用户维护Session数据,减轻了服务器的存储压力,特别是在大量用户同时访问的情况下。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。