1. 程式人生 > >Json Web Token(JWT)詳解

Json Web Token(JWT)詳解

再次 即使 設備 系統 客戶 利用 fck 第三方服務 ont

什麽是Json Web Token

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

為什麽要用Json Web Token

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

技術分享圖片

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

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

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

4.CSRF(跨站請求偽造):用戶在訪問銀行網站時,他們很容易受到跨站請求偽造的攻擊,並且能夠被利用其訪問其他的網站。

5、當服務器應用重啟時,用戶會被強制登出

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

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


Json Web Token是怎麽做的

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

1、客戶端通過用戶名和密碼登錄服務器;
2、服務端對客戶端身份進行驗證;
3、服務端對該用戶生成Token,返回給客戶端;
4、客戶端將Token保存到本地瀏覽器,一般保存到cookie中;
5、客戶端發起請求,需要攜帶該Token;
6、服務端收到請求後,首先驗證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-

如果你覺得本文對你有用,請轉發支持一下

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

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

技術分享圖片

在公眾號後臺回復“前端資源”即可獲取最新前端開發資源

Json Web Token(JWT)詳解