本文章內容翻譯自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 結構是什么?
JWT的結構是緊湊的(之前在第一部分定義中說過),在其緊湊的形式中,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 //是否是管理員
}
然后,對有效載荷這個JSON進行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 Token?
下面我們談一談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……