“簡介JSON Web Token 機制與使用情境”
1. 什麼是 JWT ?
JSON Web Token (JWT) 是 Auth0 提構出的一個新 Token 想法,一個 JWT 的長相會像下面這樣。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
他的構成如下。
Header.Payload.Signature
1.1. Header
標頭包含了 alg
簽章或加密演算法與 typ
Token 的類型。
{
"alg": "HS256",
"typ": "JWT"
}
目前所支持的演算法如下。
alg Parameter Value | Digital Signature or MAC Algorithm |
---|---|
HS256 | HMAC using SHA-256 hash algorithm |
HS384 | HMAC using SHA-384 hash algorithm |
HS512 | HMAC using SHA-512 hash algorithm |
RS256 | RSASSA using SHA-256 hash algorithm |
RS384 | RSASSA using SHA-384 hash algorithm |
RS512 | RSASSA using SHA-512 hash algorithm |
ES256 | ECDSA using P-256 curve and SHA-256 hash algorithm |
ES384 | ECDSA using P-384 curve and SHA-384 hash algorithm |
ES512 | ECDSA using P-521 curve and SHA-512 hash algorithm |
none | No digital signature or MAC value included |
1.2. Claims(Payload)
Claims部分包含了一些跟這個 Token 有關的重要信息。JWT標準規定了一些字段,下面為部分字段:
iss
:Token 的發行者,令牌是給誰的sub
:Token 主題,令牌主題exp
:到期時間。Token 過期時間,Unix時間戳格式iat
:發佈時間。Token 創建時間,Unix時間戳格式jti
:JWT ID。針對當前 Token 的唯一標識
Payload 格式如下。
{
"iss": "John Wu JWT",
"iat": 1441593502,
"exp": 1441594722,
"aud": "www.example.com",
"sub": "jrocket@example.com",
"id": "UxHeJOke5C4E"
}
1.3. Signature
簽章的部分為將 Header 與 Claims 透過 Base64 轉換,再依據在 Header 中的演算類型加密,所使用的secret
只有簽章的 Server 知道所以攻擊者無法偽造內容除非暴力解,因為是以 Base64 轉換的所以不適合把重要資訊放在當中。
content = base64url_encode(Header) + '.' + base64url_encode(Claims)
signature = hmacsha256.hash(content)
2. 與傳統 Session 有什麼不同
傳統使用 Session 在 Server 端需要將用來識別使用者的 Token 紀錄在快取或資料庫中,如下圖,每次 request 進來經過 Load Balance 進到不同的 Backend Server,會造成在 Server1 可以識別,而 Server2 沒有用戶的 Session 所以無法識別出是誰的請求,可以透過一個共用的快取(Radis)或資料庫解決這個問題,但在這樣的分散式系統中這會造成維護與架構上的複雜度提高。
3. 使用 JWT 的好處
3.1. 跨服務認證
JWT 本身為無狀態性的
(Stateless),當 Backend Server 收到 Token 再依據定義在 Header 中的 alg
進行解密,所以不需要使用資料庫額外紀錄才能做到識別用戶,這樣的機制方便於實作 Single sign-on 與 Load Balance 架構。
3.2. 提升安全性
傳統 Session 的機制如果惡意的攻擊者傳送如:刪除帳號等,危險操做的連結給用戶,用戶在不知情得其況下點擊連結,用戶的瀏覽器便會將 cookie 帶入請求中,Backend Server 收到請求便會認為是用戶正常操作,將用戶帳號刪除。而 JWT 機制在點擊惡意連結時,因連結不帶有 Token
,所以該操做不會被執行。
3.3. 降低資料庫負載
後端收到 Token 在 middleware 層便可以識別用戶,不需要每次去資料庫中詢問這個使用者是誰,大幅度的減少在認證過程中資料庫的負擔。
4. 適合的使用時機
- JWT 其實很單純做的只有一件事情,就是發識別牌,所以當將 Token 簽出去的瞬間變沒辦法對 Token 的內容做修該,只能等到 Token 過期,所以重設密碼或希望強制需要而外實作機制過濾 Token 但這就無法享受跨服務認證的好處,所以比較適合的方式為將
exp
的時間設為固定時間,確保在該時間用戶便無法使用或expiresIn
時間設定短一點,讓用戶需要refresh
或login
。 - Token 為 Base64 加密,所以不適合在 Token Payload 中放入重要的資訊,避免任意的使用者可以透過 Base64 解密看到用戶重要的資訊。
5. 認證流程
- client端發送登入的請求,這時可能會附上帳號密碼等驗證資訊,server端驗證登入資訊後,搭配一個密鑰(secret key)來產生JWT token
- 將token回傳給client端。
- client端請求資料時,在request header的Authoriaztion中加上這個token,server端驗證token的簽章是否正確,並從payload中得知user的資訊。
- 驗證無誤的話,回傳client端請求的資料
6. 參考
comments powered by Disqus