JWT 介紹
JSON Web Token(JWT)是為了在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明而執(zhí)行的一種基于 JSON 的開放標準(RFC 7519)箫措。來自 JWT RFC 7519 標準化的摘要說明:JSON Web Token 是一種緊湊的,URL 安全的方式权薯,表示要在雙方之間傳輸?shù)穆暶鳌WT 一般被用來在身份提供者和服務(wù)提供者間傳遞被認證的用戶身份信息锣枝,以便于從資源服務(wù)器獲取資源扫尺,也可以增加一些額外的其它業(yè)務(wù)邏輯所必須的聲明信息,該 Token 也可直接被用于認證咒彤,也可被加密疆柔。
JWT 認證流程
- 客戶端調(diào)用登錄接口(或者獲取 token 接口),傳入用戶名密碼镶柱。
- 服務(wù)端請求身份認證中心旷档,確認用戶名密碼正確。
- 服務(wù)端創(chuàng)建 JWT歇拆,返回給客戶端鞋屈。
- 客戶端拿到 JWT,進行存儲(可以存儲在緩存中故觅,也可以存儲在數(shù)據(jù)庫中厂庇,如果是瀏覽器,可以存儲在 Cookie 中)在后續(xù)請求中输吏,在 HTTP 請求頭中加上 JWT权旷。
- 服務(wù)端校驗 JWT,校驗通過后评也,返回相關(guān)資源和數(shù)據(jù)炼杖。
JWT 結(jié)構(gòu)
JWT 是由三段信息構(gòu)成的灭返,第一段為頭部(Header)盗迟,第二段為載荷(Payload),第三段為簽名(Signature)熙含。每一段內(nèi)容都是一個 JSON 對象罚缕,將每一段 JSON 對象采用 BASE64 編碼,將編碼后的內(nèi)容用. 鏈接一起就構(gòu)成了 JWT 字符串怎静。如下:
header.payload.signature
1. 頭部(Header)
頭部用于描述關(guān)于該 JWT 的最基本的信息邮弹,例如其類型以及簽名所用的算法等。這也可以被表示成一個 JSON 對象蚓聘。
<pre>{
"typ": "JWT",
"alg": "HS256"
}</pre>
在頭部指明了簽名算法是 HS256 算法腌乡。
2. 載荷(payload)
載荷就是存放有效信息的地方。有效信息包含三個部分:
標準中注冊的聲明
公共的聲明
私有的聲明
標準中注冊的聲明(建議但不強制使用):
iss:JWT 簽發(fā)者
sub:JWT 所面向的用戶
aud:接收 JWT 的一方
exp:JWT 的過期時間夜牡,這個過期時間必須要大于簽發(fā)時間
nbf:定義在什么時間之前与纽,該 JWT 都是不可用的
iat:JWT 的簽發(fā)時間
jti:JWT 的唯一身份標識,主要用來作為一次性 token, 從而回避重放攻擊塘装。
公共的聲明 :
公共的聲明可以添加任何的信息急迂,一般添加用戶的相關(guān)信息或其他業(yè)務(wù)需要的必要信息. 但不建議添加敏感信息,因為該部分在客戶端可解密蹦肴。
私有的聲明 :
私有聲明是提供者和消費者所共同定義的聲明僚碎,一般不建議存放敏感信息,因為 base64 是對稱解密的阴幌,意味著該部分信息可以歸類為明文信息勺阐。
示例如下:
<pre>{ "iss": "Online JWT Builder",
"iat": 1416797419,
"exp": 1448333419,
"aud": "www.primeton.com",
"sub": "devops@primeton.com",
"GivenName": "dragon",
"Surname": "wang",
"admin": true
}</pre>
3. 簽名(signature)
創(chuàng)建簽名需要使用 Base64 編碼后的 header 和 payload 以及一個秘鑰卷中。將 base64 加密后的 header 和 base64 加密后的 payload 使用. 連接組成的字符串,通過 header 中聲明的加密方式進行加鹽 secret 組合加密皆看,然后就構(gòu)成了 jwt 的第三部分仓坞。
比如:HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
JWT 的優(yōu)點:
- 跨語言,JSON 的格式保證了跨語言的支撐
- 基于 Token腰吟,無狀態(tài)
- 占用字節(jié)小无埃,便于傳輸
關(guān)于 Token 注銷:
Token 的注銷,由于 Token 不存儲在服務(wù)端毛雇,由客戶端存儲嫉称,當(dāng)用戶注銷時,Token 的有效時間還沒有到灵疮,還是有效的织阅。所以如何在用戶注銷登錄時讓 Token 注銷是一個要關(guān)注的點。一般有如下幾種方式:
- Token 存儲在 Cookie 中震捣,這樣客戶端注銷時荔棉,自然可以清空掉
- 注銷時,將 Token 存放到分布式緩存中蒿赢,每次校驗 Token 時去檢查下該 Token 是否已注銷润樱。不過這樣也就失去了快速校驗 Token 的優(yōu)點。
- 多采用短期令牌羡棵,比如令牌有效期是 20 分鐘壹若,這樣可以一定程度上降低注銷后 Token 可用性的風(fēng)險。