Json Web Token(JWT)詳解

 

什麼是Json Web Tokenjavascript

Json web token (JWT), 是爲了在網絡應用環境間傳遞聲明而執行的一種基於JSON的開放標準((RFC 7519).該token被設計爲緊湊且安全的,特別適用於分佈式站點的單點登陸(SSO)場景。JWT的聲明通常被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源,也能夠增長一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用於認證,也可被加密。前端

爲何要用Json Web Tokenjava

       咱們知道HTTP通訊是無狀態的,所以客戶端的請求到了服務端處理完以後是沒法返回給原來的客戶端。所以須要對訪問的客戶端進行識別,經常使用的作法是經過session機制:客戶端在服務端登錄成功以後,服務端會生成一個sessionID,返回給客戶端,客戶端將sessionID保存到cookie中,再次發起請求的時候,攜帶cookie中的sessionID到服務端,服務端會緩存該session(會話),當客戶端請求到來的時候,服務端就知道是哪一個用戶的請求,並將處理的結果返回給客戶端,完成通訊。流程圖以下。web

 

1.服務器開銷過大:每次認證用戶發起請求時,服務器須要去建立一個Seesion記錄來存儲信息。當愈來愈多的用戶發請求時,內存的開銷也會不斷增長。算法

2.可擴展性:在服務端的內存中使用Seesion存儲登陸信息,伴隨而來的是可擴展性問題。後端

3.CORS(跨域資源共享):當咱們須要讓數據跨多臺移動設備上使用時,跨域資源的共享會是一個讓人頭疼的問題。在使用Ajax抓取另外一個域的資源,就能夠會出現禁止請求的狀況。api

4.CSRF(跨站請求僞造):用戶在訪問銀行網站時,他們很容易受到跨站請求僞造的攻擊,而且可以被利用其訪問其餘的網站。跨域

五、當服務器應用重啓時,用戶會被強制登出瀏覽器

六、當站點用負載均衡部署多份時,每一個站點實例的session沒法共享。固然,咱們可使用單獨的session存儲服務來解決這些問題,但這樣會增長系統不小的複雜性與維護成本。 緩存

在這些問題中,可擴展性是最突出的。所以咱們有必要去尋求一種更有行之有效的方法。


Json Web Token是怎麼作的

使用基於 Token 的身份驗證方法,在服務端不須要存儲用戶的登陸記錄。大概的流程是這樣的: 

      一、客戶端經過用戶名和密碼登陸服務器;
      二、服務端對客戶端身份進行驗證;
      三、服務端對該用戶生成Token,返回給客戶端;
      四、客戶端將Token保存到本地瀏覽器,通常保存到cookie中;
      五、客戶端發起請求,須要攜帶該Token;
      六、服務端收到請求後,首先驗證Token,以後返回數據。

 

使用token認證有如下優勢:

1.無狀態、可擴展 :在客戶端存儲的Token是無狀態的,而且可以被擴展。基於這種無狀態和不存儲Session信息,負載均衡器可以將用戶信息從一個服務傳到其餘服務器上。

2.安全性 

請求中發送token而再也不是發送cookie可以防止CSRF(跨站請求僞造)。即便在客戶端使用cookie存儲token,cookie也僅僅是一個存儲機制而不是用於認證。不將信息存儲在Session中,讓咱們少了對session操做。token是有時效的,一段時間以後用戶須要從新驗證。咱們也不必定須要等到token自動失效,token有撤回的操做,經過token revocataion可使一個特定的token或是一組有相同認證的token無效。

3.提供接口給第三方服務

使用tokens時,能夠提供可選的權限給第三方應用程序。當用戶想讓另外一個應用程序訪問它們的數據,咱們能夠經過創建本身的API,得出特殊權限的tokens。

4.多平臺跨域 

對應用程序和服務進行擴展的時候,須要介入各類各類的設備和應用程序。 

假如咱們的後端api服務器a.com只提供數據,而靜態資源則存放在cdn 服務器b.com上。當咱們從a.com請求b.com下面的資源時,因爲觸發瀏覽器的同源策略限制而被阻止。

咱們經過CORS(跨域資源共享)標準和token來解決資源共享和安全問題。

舉個例子,咱們能夠設置b.com的響應首部字段爲:

Access-Control-Allow-Origin: http://a.com

Access-Control-Allow-Headers: Authorization, X-Requested-With, Content-Type, Accept

Access-Control-Allow-Methods: GET, POST, PUT,DELETE

第一行指定了容許訪問該資源的外域 URI

第二行指明瞭實際請求中容許攜帶的首部字段,這裏加入了Authorization,用來存放token

第三行用於預檢請求的響應。其指明瞭實際請求所容許使用的 HTTP 方法。

而後用戶從a.com攜帶有一個經過了驗證的token訪問B域名,數據和資源就可以在任何域上被請求到。 

 

Json Web Token長什麼樣子呢?

一個JWT實際就是一個字符串,它包含三部分,分別是: 頭部(header ),載荷(payload ),簽名 (signature)。

他們按照 A.B.C 的格式拼接起來,其中C由A和B生成,他們之間的格式爲 Base64(header).Base64(payload).H256(A.B)。須要注意的是header和payload都是使用Base64URL 算法對象序列化以後的字符串. 

一個JWT大概長這樣:

 

 頭部(header)

Header 部分是一個 JSON 對象,描述 JWT 的元數據,通常不多改動直接使用默認的便可            

{

    'typ': 'JWT',

    'alg': 'HS256'

}

 

alg屬性表示簽名的算法(algorithm),默認是 HMAC SHA256(寫成 HS256);typ屬性表示這個令牌(token)的類型(type),JWT 令牌統一寫爲JWT。


  載荷(playload)

Payload 部分也是一個 JSON 對象,用來存放實際須要傳遞的數據。

可自行指定字段很靈活,也有固定字段表示特定含義(但不必定要包含特定字段,只是推薦)。下面是官方推薦的字段:

            {
                    'iss':'簽發者',
                    'sub':'面向的用戶',
                    'aud':'接收方',
                    'exp':  過時時間,
                    'iat':  建立時間,
                    'nbf':  在什麼時間以前,該Token不可用,
                    'jti':'Token惟一標識'
             }

下面就是一個例子:

{

"sub": "1234567890",

"name": "John Doe",

"admin": true

}

 

簽名(signature)

Signature 部分是對前兩部分的簽名,防止數據篡改。

首先,須要指定一個密鑰(secret)。這個密鑰只有服務器才知道,不能泄露給用戶。而後,使用 Header 裏面指定的簽名算法(默認是 HMAC SHA256),按照下面的公式產生簽名。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

 

算出簽名之後,如今把header和payload用Base64URL 算法對象序列化,而後把這三部分用「.」拼接起來就是生成的token了。

 

怎樣使用token?

能夠放到HTTP請求的請求頭中,一般是Authorization字段。
也有人說放到cookie。不過移動端app用cookie彷佛不方便。

 

-END-

 

若是你以爲本文對你有用,請轉發支持一下

長按並識別下方二維碼,點擊關注,便可獲取最新走心文章

記得把我設爲星標或置頂哦

 

在公衆號後臺回覆「前端資源」便可獲取最新前端開發資源

相關文章
相關標籤/搜索