JSON Web Token(JWT)是一個開放式標準(RFC 7519),它定義了一種緊湊(Compact)且自包含(Self-contained)的方式,用於在各方之間以JSON對象安全傳輸信息。 這些信息能夠經過數字簽名進行驗證和信任。 可使用祕密(使用HMAC算法)或使用RSA的公鑰/私鑰對對JWT進行簽名。html
雖然JWT能夠加密以提供各方之間的保密性,但咱們將重點關注已簽名的令牌。 簽名的令牌能夠驗證其中包含的索賠的完整性,而加密令牌隱藏來自其餘方的索賠。 當令牌使用公鑰/私鑰對進行簽名時,簽名還證實只有持有私鑰的方是簽名方。算法
咱們來進一步解釋一些概念:數據庫
在緊湊的形式中,JWT包含三個由點(.)分隔的部分,它們分別是:跨域
JWT結構一般以下所示:安全
xxxxx.yyyyy.zzzzz
下面咱們分別來介紹這三個部分:服務器
Header一般由兩部分組成:令牌的類型,即JWT。和經常使用的散列算法,如HMAC SHA256或RSA。
例如:cookie
{ "alg": "HS256", "typ": "JWT" }
Header部分的JSON被Base64Url編碼,造成JWT的第一部分。session
這裏放聲明內容,能夠說就是存放溝通信息的地方,在定義上有3種聲明(Claims):less
Registered claims(註冊聲明):
這些是一組預先定義的聲明,它們不是強制性的,但推薦使用,以提供一組有用的,可互操做的聲明。 其中一些是:iss
(發行者),exp
(到期時間),sub
(主題),aud
(受衆)等。#Registered Claim Names#ide
Private claims(私有聲明):
這些是爲了贊成使用它們可是既沒有登記,也沒有公開聲明的各方之間共享信息,而建立的定製聲明。
Playload示例以下:
{ "sub": "1234567890", "name": "John Doe", "admin": true }
Playload部分的JSON被Base64Url編碼,造成JWT的第二部分。
請注意,對於已簽名的令牌,此信息儘管受到篡改保護,但任何人均可以閱讀。 除非加密,不然不要將祕密信息放在JWT的有效內容或標題元素中。這也是不少文章爭論jwt安全性緣由,不要用 JWT 取代 Server-side 的 Session狀態機制。詳情請閱讀這篇文章:Stop Using Jwt For Sessions.
第三部分signature用來驗證發送請求者身份,由前兩部分加密造成。
要建立簽名部分,您必須採用編碼標頭,編碼有效載荷,祕鑰,標頭中指定的算法並簽名。
例如,若是你想使用HMAC SHA256算法,簽名將按照如下方式建立:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
JWT輸出的是三個由點分隔的Base64-URL字符串,能夠在HTML和HTTP環境中輕鬆傳遞,而與基於XML的標準(如SAML)相比,它更加緊湊。
如下JWT示例,它具備先前的標頭和有效負載編碼,而且使用祕鑰進行簽名。
咱們可使用jwt.io調試器來解碼,驗證和生成JWT:
在身份驗證中,當用戶使用他們的憑證成功登陸時,JSON Web Token將被返回而且必須保存在本地(一般在本地存儲中,但也可使用Cookie),而不是在傳統方法中建立會話 服務器並返回一個cookie。
關於存儲令牌(Token)的方式,必須考慮安全因素。
參考: #Where to Store Tokens#
不管什麼時候用戶想要訪問受保護的路由或資源,用戶代理都應使用承載方案發送JWT,一般在請求頭中的Authorization
字段,使用Bearer
schema:
Authorization: Bearer <token>
這是一種無狀態身份驗證機制,由於用戶狀態永遠不會保存在服務器內存中。 服務器受保護的路由將在受權頭中檢查有效的JWT,若是存在,則容許用戶訪問受保護的資源。 因爲JWT是獨立的,全部必要的信息都在那裏,減小了屢次查詢數據庫的需求。
這使得咱們能夠徹底依賴無狀態的數據API,甚至向下遊服務提出請求。 不管哪些域正在爲API提供服務並不重要,所以不會出現跨域資源共享(CORS)的問題,由於它不使用Cookie。
請注意,使用已簽名的令牌,令牌中包含的全部信息都會暴露給用戶或其餘方,即便他們沒法更改它。 在JWT中,不該該在Playload裏面加入任何敏感的數據,好比像密碼這樣的內容。若是將用戶的密碼放在了JWT中,那麼懷有惡意的第三方經過Base64解碼就能很快地知道你的密碼了。
Base64編碼方式是可逆的,也就是透過編碼後發放的Token內容是能夠被解析的。通常而言,咱們都不建議在有效載荷內放敏感訊息,好比使用者的密碼。
JWT其中的一個組成內容爲Signature,能夠防止經過Base64可逆方法回推有效載荷內容並將其修改。由於Signature是經由Header跟Payload一塊兒Base64組成的。
是的,Cookie丟失,就表示身份就能夠被僞造。故官方建議的使用方式是存放在LocalStorage中,並放在請求頭中發送。
JWT Token一般長度不會過小,特別是Stateless JWT Token,把全部的數據都編在Token裏,很快的就會超過Cookie的大小(4K)或者是URL長度限制。
exp
時效不要設定太長。Only Http
預防XSS攻擊。jti
(JWT ID),exp
(有效時間) Claim。[1] Stop using JWT for sessions:
http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
[3] Use JWT The Right Way!:
https://stormpath.com/blog/jwt-the-right-way
[2] JSON Web Token 維基百科:
https://en.wikipedia.org/wiki/JSON_Web_Token