什麼是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數據,減輕了服務器的存儲壓力,特別是在大量用户同時訪問的情況下。