什么是JWT
JSON Web Token (JWT) 是一種開放標準 (RFC 7519),它定義了一種緊湊且獨立的方式,用于在各方之間以 JSON 對象的形式安全地傳輸信息。此信息可以驗證和信任,因為它是經過數字簽名的。JWT 可以使用密鑰(使用 HMAC算法)或使用 RSA 或 ECDSA 的公鑰/私鑰對進行簽名。
簡單來說,JWT就是用來判斷某種信息是否可以被信任的一種簽名json
JWT使用場景
1. 身份驗證(Authentication):JWT 可以被用作用戶登錄的身份驗證憑證。當用戶成功登錄后,服務端可以生成一個包含用戶信息的 JWT,并將其返回給客戶端。以后,客戶端在每次請求時都會攜帶這個 JWT,服務端通過驗證 JWT 的簽名來確認用戶的身份。
2. 授權(Authorization):在用戶登錄后,服務端可以生成包含用戶角色、權限等信息的 JWT,并在用戶每次請求時進行驗證。通過解析 JWT 中的聲明信息,服務端可以判斷用戶是否有權限執行特定的操作或訪問特定的資源。
3. 信息交換(Information Exchange):由于 JWT 的聲明信息可以被加密,因此可以安全地在用戶和服務器之間傳遞信息。這在分布式系統中非常有用,因為可以確保信息在各個環節中的安全傳遞。
4. 單點登錄(Single Sign-On):JWT 可以被用于支持單點登錄,使得用戶在多個應用之間只需要登錄一次即可使用多個應用,從而提高用戶體驗。
JWT優勢
無狀態:JWT 的驗證是基于密鑰的,因此它不需要在服務端存儲用戶信息。這使得 JWT 可以作為一種無狀態的身份認證機制。
跨語言支持:JWT 的標準化和簡單性質使得它可以在多種語言和平臺之間使用。
安全性高:由于 JWT 的載荷可以進行加密處理,因此 JWT 能夠保證數據的安全傳輸。同時,JWT 的簽名機制也能夠保證數據的完整性和真實性。
為什么需要JWT
在一些web項目中,使用Cookie-Session
模式實現用戶認證的相關流程大致如下:
- 用戶在瀏覽器端填寫用戶名和密碼,并發送給服務端
- 服務端對用戶名和密碼校驗通過后會生成一份保存當前用戶相關信息的session數據和一個與之對應的標識(通常稱為session_id)
- 服務端返回響應時將上一步的session_id寫入用戶瀏覽器的Cookie
- 后續用戶來自該瀏覽器的每次請求都會自動攜帶包含session_id的Cookie
- 服務端通過請求中的session_id就能找到之前保存的該用戶那份session數據,從而獲取該用戶的相關信息。
這種方案依賴于客戶端(瀏覽器)保存 Cookie,并且需要在服務端存儲用戶的session數據。
在移動互聯網時代,用戶可能使用瀏覽器也可能使用APP來訪問服務器,我們的web應用可能是前后端分開部署在不同的端口,有時候我們還需要支持第三方登錄,這下Cookie-Session
的模式就有些力不從心了。
JWT就是一種基于Token的輕量級認證模式,服務端認證通過后,會生成一個JSON對象,經過簽名后得到一個Token(令牌)再發回給用戶,用戶后續請求只需要帶上這個Token,服務端解密之后就能獲取該用戶的相關信息了。
JWT的結構
JWT由三部分組成,使用.
分隔,他們是:
- Header(頭部)
- Payload(載荷)
- Signature(簽名)
Header
JWT頭部通常由兩部分組成:令牌的類型(JWT)和正在使用的簽名算法,例如 HMAC SHA256 或 RSA。
{"alg": "HS256","typ": "JWT"
}
然后,JSON 數據經過 Base64Url 編碼以形成 JWT 的第一部分。
Payload
JWT 的載荷也稱為聲明信息,包含了一些有關實體(通常是用戶)的信息以及其他元數據。有三種類型的聲明:已注冊、公共和私有聲明。
- **已注冊的聲明(Registered Claims):**這些是一組預定義的聲明,不是強制性的,但建議使用,以提供一組有用的、可互操作的聲明。包括 iss(發行者)、sub(主題)、aud(受眾)、exp(過期時間)、nbf(生效時間)、iat(發布時間)和 jti(JWT ID)等。
注意:聲明名稱只有三個字符長,因為JWT是緊湊的
-
**公共聲明(Public claims):**這些聲明可以由使用 JWT 的用戶隨意定義。但為避免沖突,應在 IANA JSON Web 令牌注冊表中定義它們,或將其定義為包含抗沖突命名空間的 URI。
-
**私有聲明(Private Claims):**這些聲明是保留給特定的應用程序使用的,不會與其他應用程序沖突。
示例有效負載:
{"sub": "123456789","name": "John","admin": true
}
注意:注意,對于簽名令牌,此信息雖然可以防止篡改,但任何人都可以讀取。除非 JWT 已加密,否則不要將機密信息放在 JWT 的 payload 或 header 元素中。
對有效負載進行 Base64Url 編碼,以形成 JSON Web 令牌的第二部分。
Signature
JWT 的簽名是由頭部、載荷和密鑰共同生成的。它用于驗證 JWT 的真實性和完整性。一般情況下,簽名也會采用 Base64 編碼。
例如,如果要使用 HMAC SHA256 算法,將按以下方式創建簽名:
HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)
簽名用于驗證消息在整個過程中沒有被更改,并且在使用私鑰簽名的令牌的情況下,它還可以驗證 JWT 的發件人是否是它所聲稱的身份。