如今愈來愈多的項目或多或少會用到JWT,爲何會出現使用JWT這樣的場景的呢?javascript
假設如今有一個APP,後臺是分佈式系統。APP的首頁模塊部署在上海機房的服務器上,子頁面模塊部署在深圳機房的服務器上。此時你從首頁登陸了該APP,而後跳轉到子頁面模塊。session在兩個機房之間不能同步,用戶是否須要從新登陸?java
傳統的方式(cookie+session)須要從新登陸,用戶體驗很差。session共享(在多臺物理機之間傳輸和複製session)方式對網絡IO的壓力大,延遲太長,用戶體驗也很差。web
說到這你們可能會想到,用服務器的session_id存儲到cookies中也能作到,爲何非要用token呢?網上有許多文章來比較token和session的優缺點,其實,開發web應用的話用哪一種都行。但若是是開發api接口,先後端分離,最好使用token,爲何這麼說呢,由於session+cookies是基於web的。可是針對 api接口,可能會考慮到移動端,app是沒有cookies和session的。算法
Session方式存儲用戶信息的最大問題在於要佔用大量服務器內存,增長服務器的開銷。後端
而JWT方式將用戶狀態分散到了客戶端中,能夠明顯減輕服務端的內存壓力。Session的狀態是存儲在服務器端,客戶端只有session id;而Token的狀態是存儲在客戶端api
JSON Web Token(縮寫 JWT)跨域
JWT 的原理是,服務器認證之後,生成一個 JSON 對象,發回給用戶,之後,用戶與服務端通訊的時候,都要發回這個 JSON 對象。安全
服務器徹底只靠這個對象認定用戶身份。爲了防止用戶篡改數據,服務器在生成這個對象的時候,會加上簽名。服務器
服務器就不保存任何 session 數據了,也就是說,服務器變成無狀態了,從而比較容易實現擴展。cookie
JWT 的三個部分依次是:Header(頭部)、Payload(負載)、Signature(簽名)
寫成一行,就是下面的樣子。
Header.Payload.Signature
1、Header
header典型的由兩部分組成:token的類型(「JWT」)和算法名稱(好比:HMAC SHA256或者RSA等等)
{ "alg": "HS256", //alg屬性表示簽名的算法(algorithm),默認是 HMAC SHA256(寫成 HS256) "typ": "JWT" //typ屬性表示這個令牌(token)的類型(type) }
而後用Base64對這個JSON編碼就獲得JWT的第一部分
2、Payload
JWT的第二部分是payload,它包含聲明(要求)。聲明是關於實體(一般是用戶)和其餘數據的聲明
JWT 規定了7個官方字段
除了官方字段,你還能夠在這個部分定義私有字段,下面就是一個例子
{ "sub": "1234567890", "name": "John Doe", "admin": true }
注意,不要在JWT的payload或header中放置敏感信息,除非它們是加密的
3、Signature
Signature 部分是對前兩部分的簽名,防止數據篡改。簽名是用於驗證消息在傳遞過程當中有沒有被更改,而且,對於使用私鑰簽名的token,它還能夠驗證JWT的發送方是否爲它所稱的發送方。
爲了獲得簽名部分,你必須有編碼過的header、編碼過的payload、一個祕鑰,簽名算法是header中指定的那個,然對它們簽名便可。按照下面的公式產生簽名。
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
算出簽名之後,把 Header、Payload、Signature 三個部分拼成一個字符串,每一個部分之間用"點"(.
)分隔,就能夠返回給用戶。
1、客戶端收到服務器返回的 JWT,能夠儲存在 Cookie 裏面,也能夠儲存在 localStorage。
此後,客戶端每次與服務器通訊,都要帶上這個 JWT。你能夠把它放在 Cookie 裏面自動發送,可是這樣不能跨域,因此更好的作法是放在 HTTP 請求的頭信息Authorization
字段裏面。
Authorization: Bearer <token>
2、JWT 就放在 POST 請求的數據體裏面,那麼跨源資源共享(CORS)將不會成爲問題,由於它不使用cookie
1.應用(或者客戶端)想受權服務器請求受權。例如,若是用受權碼流程的話,就是/oauth/authorize
2.當受權被許能夠後,受權服務器返回一個access token給應用
3.應用使用access token訪問受保護的資源(好比:API)
1.JWT 默認是不加密,但也是能夠加密的。生成原始 Token 之後,能夠用密鑰再加密一次。
2.JWT 不加密的狀況下,不能將祕密數據寫入 JWT。
3.JWT 的最大缺點是,因爲服務器不保存 session 狀態,所以沒法在使用過程當中廢止某個 token,或者更改 token 的權限。也就是說,一旦 JWT 簽發了,在到期以前就會始終有效,除非服務器部署額外的邏輯。
4.JWT 自己包含了認證信息,一旦泄露,任何人均可以得到該令牌的全部權限。爲了減小盜用,JWT 的有效期應該設置得比較短。對於一些比較重要的權限,使用時應該再次對用戶進行認證。
注意:
JWT 是 JSON 格式的被加密了的字符串
JWT 的核心是密鑰,就是 JSON 數據。這是你關心的,並但願安全傳遞出去的數據。JWT 如何作到這一點,並使你信任它,就是加密簽名。
被篡改以後
參考官方文檔:JSON Web Tokens