本文章內容翻譯自JWT官網,並融入了部分筆者的思想內容。希望給其他小夥伴在學習這部分內容時帶來一定的幫助。
一、什麼是JWT?
JWT是簡寫,全稱是JSON Web Token。
JSON Web Token(JWT)是一種開放標準(RFC 7519),它定義了一種緊湊(Compact)且自包含(Self-contained)的方式,用於在各方之間以JSON物件的形式安全傳輸資訊。此資訊可以驗證和信任,因為它是經過數字簽名的。JWT可以使用金鑰(使用HMAC演算法)或使用RSA或ECDSA的公鑰/私鑰對進行簽名。
下面進一步解釋這個定義中的一些概念:
·緊湊(Compact):由於它的大小,它可以通過 URL、POST 引數或 HTTP 標頭內部傳送。此外,由於它的大小,它的傳輸速度很快。
·自包含(Self-contained):有效載荷(後面介紹)中包含有關使用者的所有必需資訊,可以避免多次查詢資料庫。
雖然JWT可以加密以在各方之間提供保密性,但我們將重點專注於簽名令牌。簽名的令牌可以驗證其中包含的宣告的完整性,而加密的令牌會向其他方隱藏這些宣告。當使用公鑰/私鑰對對令牌進行簽名時,簽名還證明只有持有私鑰的一方才是簽署它的一方。
二、什麼時候應該使用 JSON Web Token?
以下是一些JSON Web token非常有用的場景:
- 授權(Authorization):這是使用JWT最常見的場景。使用者登入後,每個後續請求都將包含JWT,從而允許使用者訪問該令牌允許的路由、服務和資源。單點登入是當今廣泛使用JWT的一項功能,因為它的開銷很小,並且能夠在不同的域中輕鬆使用。
- 資訊交換(Information Exchange):JSON Web Token是在各方之間安全傳輸資訊的好方法。因為可以對 JWT 進行簽名(例如,使用公鑰/私鑰對),所以您可以確定發件人就是他們所說的那個人。此外,由於使用標頭和有效負載計算簽名,您還可以驗證內容沒有被篡改。
三、JSON Web Token 結構是什麼?
在其緊湊的形式中,JSON Web token由三部分組成,三部分由點(.)分隔,它們是:
- 標頭(Header)
- 有效載荷(Payload)
- 簽名(Signature)
因此,JWT結構通常如下所示:
xxxxx.yyyyy.zzzzz
接下來,讓我們把不同的部分分解一下。
1、標頭(Header)
標頭通常由兩部分組成:
- 令牌的型別,即JWT
- 正在使用的簽名演算法,例如HMAC SHA256或RSA。
例如:
{
"alg": "HS256", //簽名演算法
"typ": "JWT" //型別
}
然後,這個 JSON 被Base64Url編碼以形成 JWT 的第一部分。
2、有效載荷(Payload)
令牌的第二部分是有效載荷,其中包含宣告。宣告是關於實體(通常是使用者)和附加資料的陳述。宣告分為三種型別:
- 註冊(registered)宣告
- 公開(public)宣告
- 私有(private )宣告
- 註冊宣告(Registered claims):這些是一組預定義的宣告,它們不是強制性的,但建議使用,以提供一組有用的、可互操作的宣告。其中一些是: iss(發行人)、 exp(到期時間)、 sub(主題)、 aud(受眾)等。
請注意,宣告名稱只有三個字元長,因為JWT是緊湊的。
- 公開宣告(Public claims):這些可以由使用 JWT 的人隨意定義。但是為了避免衝突,它們應該在IANA JSON Web Token Registry中定義,或者定義為包含抗衝突名稱空間的 URI。
- 私人宣告(Private claims):這些是為在同意使用它們的各方之間共享資訊而建立的自定義宣告,既不是註冊宣告也不是公共宣告。
一個有效載荷的示例可能是下面這個樣子:
{
"iss": "xx網站", //發行人
"name": "張歐昊辰", //全名
"email": "mwstars@163.com", //郵箱
"admin": true //是否是管理員
}
然後,對有效負載進行Base64Url編碼以形成 JWT的第二部分。
- 請注意,對於已簽名的令牌,此資訊雖然受到保護以防篡改,但任何人都可以讀取。除非已加密,否則請勿將機密資訊放入 JWT 的有效負載或標頭元素中。
3、簽名(Signature)
要建立簽名部分,必須獲取編碼的標頭、編碼的有效負載、金鑰、標頭中指定的演算法,並對其進行簽名。
例如,如果想使用 HMAC SHA256 演算法,簽名將通過以下方式建立:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
簽名用於驗證訊息在此過程中沒有被更改,並且在使用私鑰簽名的令牌的情況下,它還可以驗證 JWT 的傳送者就是它所說的那個人。
4、把所有的放在一起
輸出是三個用點分隔的 Base64-URL 字串,可以在 HTML 和 HTTP 環境中輕鬆傳遞,同時與基於 XML 的標準(如 SAML)相比更緊湊。
下面顯示了一個 JWT,該 JWT 具有先前的標頭和有效負載編碼,並使用金鑰簽名。
四、JSON Web Token是如何工作?
在身份驗證中,當使用者使用其憑據成功登入時,將返回一個 JSON Web Token。由於令牌是憑據,因此必須非常小心以防止出現安全問題。通常,不應將令牌保留超過所設定的過期時間。
由於缺乏安全性,也不應該在瀏覽器儲存中儲存敏感的會話資料。
每當使用者想要訪問受保護的路由或資源時,使用者代理應該傳送 JWT,通常在Authorization標頭中使用Bearer模式。
標頭的內容應如下所示:
Authorization: Bearer <token>
在某些情況下,這可以是一種無狀態授權驗證機制,因為使用者狀態永遠不會儲存在伺服器記憶體中。伺服器的受保護路由將檢查Authorization標頭中是否存在有效的 JWT,如果存在,則允許使用者訪問受保護的資源。由於 JWT 是自包含的,所有必要的資訊都在那裡,減少了返回和轉發到資料庫的需要。
這允許完全依賴無狀態的資料 API,甚至可以向下遊服務發出請求。如果令牌在Authorization標頭中傳送,則跨域資源共享 (CORS) 不會成為問題,因為它不使用 cookie。
特別注意,使用簽名令牌時,令牌中包含的所有資訊都會向使用者或其他方公開,即使他們無法更改,這也意味著不應將祕密資訊放入令牌中。
五、為什麼我們應該使用 JSON Web Tokens?
下面我們談一談JSON Web Tokens (JWT)與Simple Web Tokens (SWT)和Security Assertion Markup Language Tokens (SAML)相比的優勢。
- 由於 JSON 不像 XML 那樣冗長,因此在對其進行編碼時,它的大小也更小,這使得 JWT 比 SAML 更緊湊。這使得 JWT 成為在 HTML 和 HTTP 環境中傳遞的不錯選擇。
- 安全方面,SWT 只能通過使用 HMAC 演算法的共享金鑰進行對稱簽名。但是,JWT 和 SAML 令牌可以使用 X.509 證書形式的公鑰/私鑰對進行簽名。與簽署 JSON 的簡單性相比,使用 XML 數字簽名簽署 XML 而不引入隱蔽的安全漏洞是非常困難的。
- JSON 解析器在大多數程式語言中都很常見,因為它們直接對映到物件。相反,XML 沒有自然的文件到物件對映。這使得使用 JWT 比使用 SAML 斷言更容易。
- 關於使用,JWT 用於 Internet 規模。這突出了 JSON Web Token在多個平臺(尤其是移動平臺)上客戶端處理的便利性。
下圖為編碼的 JWT 和編碼的 SAML 的長度比較
The End……