JSON Web Token(JWT)是目前最流行的跨域身份驗證解決方案。 JWT 是一個很是輕巧的規範。這個規範容許咱們使用JWT在用戶和服務器之間傳遞安全可靠的信息。算法
一個JWT實際上就是一個字符串數據庫
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxMDAiLCJ1c2VybmFtZSI6IlpoYW5nU2FuIiwiaXNBZG1pbiI6dHJ1ZX0=.A3zvuB-qhP_oQGxCqeJ1c6uQUNAaaVOcAnMwWVeo5Qg複製代碼
字符之間經過"."
分隔符分爲三個子串,它由三部分組成,頭部(header)、載荷(payload) 與 簽名(signature)。
頭部(header) + "." + 載荷(payload) + "." + 簽名(signature)複製代碼
把它分紅三段展現// 頭部(header)
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
// 載荷(payload)
eyJ1c2VySWQiOiIxMDAiLCJ1c2VybmFtZSI6IlpoYW5nU2FuIiwiaXNBZG1pbiI6dHJ1ZX0=
// 簽名(signature)
A3zvuB-qhP_oQGxCqeJ1c6uQUNAaaVOcAnMwWVeo5Qg複製代碼
頭部用於描述關於該JWT的最基本的信息,例如其類型以及簽名所用的算法等。這也能夠被表示成一個JSON對象。json
{"typ":"JWT","alg":"HS256"}複製代碼
在頭部指明瞭簽名算法是HS256算法。 咱們進行BASE64編碼www.bejson.com/enc/base64/,編碼後的字符串以下:跨域
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9複製代碼
載荷就是存放有效信息的地方。這個名字像是特指飛機上承載的貨品,這些有效信息包含三個部分安全
(1)標準中註冊的聲明(建議但不強制使用)服務器
iss: jwt簽發者
sub: jwt所面向的用戶
aud: 接收jwt的一方
exp: jwt的過時時間,這個過時時間必需要大於簽發時間
nbf: 定義在什麼時間以前,該jwt都是不可用的.
iat: jwt的簽發時間
jti: jwt的惟一身份標識,主要用來做爲一次性token。複製代碼
(2)公共的聲明markdown
公共的聲明能夠添加任何的信息,通常添加用戶的相關信息或其餘業務須要的必要信息.但不建議添加敏感信息,由於該部分在客戶端可解密.oop
(3)私有的聲明學習
私有聲明是提供者和消費者所共同定義的聲明,通常不建議存放敏感信息,由於base64是對稱解密的,意味着該部分信息能夠歸類爲明文信息。編碼
這個指的就是自定義的claim。好比前面那個結構舉例中的admin和name都屬於自定的claim。這些claim跟JWT標準規定的claim區別在於:JWT規定的claim,JWT的接收方在拿到JWT以後,都知道怎麼對這些標準的claim進行驗證(還不知道是否可以驗證);而private claims不會驗證,除非明確告訴接收方要對這些claim進行驗證以及規則才行。
{"userId":"100","username":"ZhangSan","isAdmin":true}複製代碼
eyJ1c2VySWQiOiIxMDAiLCJ1c2VybmFtZSI6IlpoYW5nU2FuIiwiaXNBZG1pbiI6dHJ1ZX0=複製代碼
jwt的第三部分是一個簽名信息,是對上面兩部分數據簽名,經過指定的算法生成哈希,以確保數據不會被篡改。
首先,須要指定一個密碼(secret)。該密碼僅僅爲保存在服務器中,而且不能向用戶公開。而後,使用標頭中指定的簽名算法(默認狀況下爲HMAC SHA256)根據如下公式生成簽名。
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)複製代碼
這個部分須要base64加密後的header和base64加密後的payload使用.
鏈接組成的字符串,而後經過header中聲明的加密方式進行加鹽secret組合加密,而後就構成了jwt的第三部分。
A3zvuB-qhP_oQGxCqeJ1c6uQUNAaaVOcAnMwWVeo5Qg複製代碼
注意:secret是保存在服務器端的,jwt的簽發生成也是在服務器端的,secret就是用來進行jwt的簽發和jwt的驗證,因此,它就是你服務端的私鑰,在任何場景都不該該流露出去。一旦客戶端得知這個secret, 那就意味着客戶端是能夠自我簽發jwt了。客戶端接收服務器返回的JWT,將其存儲在Cookie或localStorage中。
此後,客戶端將在與服務器交互中都會帶JWT。若是將它存儲在Cookie中,就能夠自動發送,可是不會跨域,所以通常是將它放入HTTP請求的Header Authorization字段中。
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxMDAiLCJ1c2VybmFtZSI6IlpoYW5nU2FuIiwiaXNBZG1pbiI6dHJ1ZX0=.A3zvuB-qhP_oQGxCqeJ1c6uQUNAaaVOcAnMwWVeo5Qg複製代碼
當跨域時,也能夠將JWT被放置於POST請求的數據主體中。
一、JWT默認不加密,但能夠加密。生成原始令牌後,可使用改令牌再次對其進行加密。
二、當JWT未加密方法是,一些私密數據沒法經過JWT傳輸。
三、JWT不只可用於認證,還可用於信息交換。善用JWT有助於減小服務器請求數據庫的次數。
四、JWT的最大缺點是服務器不保存會話狀態,因此在使用期間不可能取消令牌或更改令牌的權限。也就是說,一旦JWT簽發,在有效期內將會一直有效。
五、JWT自己包含認證信息,所以一旦信息泄露,任何人均可以得到令牌的全部權限。爲了減小盜用,JWT的有效期不宜設置太長。對於某些重要操做,用戶在使用時應該每次都進行進行身份驗證。
六、爲了減小盜用和竊取,JWT不建議使用HTTP協議來傳輸代碼,而是使用加密的HTTPS協議進行傳輸。
若是想繼續學習 Passport 請查看我另一篇文章: 全棧之初識 Passport & Passport-jwt -- Web安全的守護神 若是想繼續學習 JWT && Passport 聯合應用 請查看我另一篇文章: 全棧之鑑權之旅 -- JWT + passport 實現 Token 驗證(Node + Express)
本文由博客一文多發平臺 OpenWrite 發佈!