認識JWT(轉)

 

1. JSON Web Token是什麼

JSON Web Token (JWT)是一個開放標準(RFC 7519),它定義了一種緊湊的、自包含的方式,用於做爲JSON對象在各方之間安全地傳輸信息。該信息能夠被驗證和信任,由於它是數字簽名的。html

2. 何時你應該用JSON Web Tokens

下列場景中使用JSON Web Token是頗有用的:node

  • Authorization (受權) : 這是使用JWT的最多見場景。一旦用戶登陸,後續每一個請求都將包含JWT,容許用戶訪問該令牌容許的路由、服務和資源。單點登陸是如今普遍使用的JWT的一個特性,由於它的開銷很小,而且能夠輕鬆地跨域使用。
  • Information Exchange (信息交換) : 對於安全的在各方之間傳輸信息而言,JSON Web Tokens無疑是一種很好的方式。由於JWTs能夠被簽名,例如,用公鑰/私鑰對,你能夠肯定發送人就是它們所說的那我的。另外,因爲簽名是使用頭和有效負載計算的,您還能夠驗證內容沒有被篡改。

3. JSON Web Token的結構是什麼樣的

JSON Web Token由三部分組成,它們之間用圓點(.)鏈接。這三部分分別是:git

  • Header
  • Payload
  • Signature

所以,一個典型的JWT看起來是這個樣子的:github

xxxxx.yyyyy.zzzzz算法

接下來,具體看一下每一部分:數據庫

Header

header典型的由兩部分組成:token的類型(「JWT」)和算法名稱(好比:HMAC SHA256或者RSA等等)。後端

例如:跨域

而後,用Base64對這個JSON編碼就獲得JWT的第一部分瀏覽器

 

Payload

JWT的第二部分是payload,它包含聲明(要求)。聲明是關於實體(一般是用戶)和其餘數據的聲明。聲明有三種類型: registered, public 和 private。安全

  • Registered claims : 這裏有一組預約義的聲明,它們不是強制的,可是推薦。好比:iss (issuer), exp (expiration time), sub (subject), aud (audience)等。
  • Public claims : 能夠隨意定義。
  • Private claims : 用於在贊成使用它們的各方之間共享信息,而且不是註冊的或公開的聲明。

下面是一個例子:

對payload進行Base64編碼就獲得JWT的第二部分

注意,不要在JWT的payload或header中放置敏感信息,除非它們是加密的。

 

Signature

爲了獲得簽名部分,你必須有編碼過的header、編碼過的payload、一個祕鑰,簽名算法是header中指定的那個,然對它們簽名便可。

例如:

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

簽名是用於驗證消息在傳遞過程當中有沒有被更改,而且,對於使用私鑰簽名的token,它還能夠驗證JWT的發送方是否爲它所稱的發送方。

 

看一張官網的圖就明白了:

4. JSON Web Tokens是如何工做的

在認證的時候,當用戶用他們的憑證成功登陸之後,一個JSON Web Token將會被返回。此後,token就是用戶憑證了,你必須很是當心以防止出現安全問題。通常而言,你保存令牌的時候不該該超過你所須要它的時間。

不管什麼時候用戶想要訪問受保護的路由或者資源的時候,用戶代理(一般是瀏覽器)都應該帶上JWT,典型的,一般放在Authorization header中,用Bearer schema。

header應該看起來是這樣的:

Authorization: Bearer <token>

服務器上的受保護的路由將會檢查Authorization header中的JWT是否有效,若是有效,則用戶能夠訪問受保護的資源。若是JWT包含足夠多的必需的數據,那麼就能夠減小對某些操做的數據庫查詢的須要,儘管可能並不老是如此。

若是token是在受權頭(Authorization header)中發送的,那麼跨源資源共享(CORS)將不會成爲問題,由於它不使用cookie。

下面這張圖顯示瞭如何獲取JWT以及使用它來訪問APIs或者資源:

  1. 應用(或者客戶端)想受權服務器請求受權。例如,若是用受權碼流程的話,就是/oauth/authorize
  2. 當受權被許能夠後,受權服務器返回一個access token給應用
  3. 應用使用access token訪問受保護的資源(好比:API)

5. 基於Token的身份認證 與 基於服務器的身份認證

5.1. 基於服務器的身份認證

在討論基於Token的身份認證是如何工做的以及它的好處以前,咱們先來看一下之前咱們是怎麼作的:

HTTP協議是無狀態的,也就是說,若是咱們已經認證了一個用戶,那麼他下一次請求的時候,服務器不知道我是誰,咱們必須再次認證

傳統的作法是將已經認證過的用戶信息存儲在服務器上,好比Session。用戶下次請求的時候帶着Session ID,而後服務器以此檢查用戶是否定證過。

這種基於服務器的身份認證方式存在一些問題:

  • Sessions : 每次用戶認證經過之後,服務器須要建立一條記錄保存用戶信息,一般是在內存中,隨着認證經過的用戶愈來愈多,服務器的在這裏的開銷就會愈來愈大。
  • Scalability : 因爲Session是在內存中的,這就帶來一些擴展性的問題。
  • CORS : 當咱們想要擴展咱們的應用,讓咱們的數據被多個移動設備使用時,咱們必須考慮跨資源共享問題。當使用AJAX調用從另外一個域名下獲取資源時,咱們可能會遇到禁止請求的問題。
  • CSRF : 用戶很容易受到CSRF攻擊。

5.2. JWT與Session的差別

相同點是,它們都是存儲用戶信息;然而,Session是在服務器端的,而JWT是在客戶端的。

Session方式存儲用戶信息的最大問題在於要佔用大量服務器內存,增長服務器的開銷。

而JWT方式將用戶狀態分散到了客戶端中,能夠明顯減輕服務端的內存壓力。

Session的狀態是存儲在服務器端,客戶端只有session id;而Token的狀態是存儲在客戶端。

 

5.3. 基於Token的身份認證是如何工做的

基於Token的身份認證是無狀態的,服務器或者Session中不會存儲任何用戶信息。

沒有會話信息意味着應用程序能夠根據須要擴展和添加更多的機器,而沒必要擔憂用戶登陸的位置。

雖然這一實現可能會有所不一樣,但其主要流程以下:

  1. 用戶攜帶用戶名和密碼請求訪問
  2. 服務器校驗用戶憑據
  3. 應用提供一個token給客戶端
  4. 客戶端存儲token,而且在隨後的每一次請求中都帶着它
  5. 服務器校驗token並返回數據

注意:

  1. 每一次請求都須要token
  2. Token應該放在請求header中
  3. 咱們還須要將服務器設置爲接受來自全部域的請求,用Access-Control-Allow-Origin: *

5.4. 用Token的好處

  • 無狀態和可擴展性:Tokens存儲在客戶端。徹底無狀態,可擴展。咱們的負載均衡器能夠將用戶傳遞到任意服務器,由於在任何地方都沒有狀態或會話信息。
  • 安全:Token不是Cookie。(The token, not a cookie.)每次請求的時候Token都會被髮送。並且,因爲沒有Cookie被髮送,還有助於防止CSRF攻擊。即便在你的實現中將token存儲到客戶端的Cookie中,這個Cookie也只是一種存儲機制,而非身份認證機制。沒有基於會話的信息能夠操做,由於咱們沒有會話!

還有一點,token在一段時間之後會過時,這個時候用戶須要從新登陸。這有助於咱們保持安全。還有一個概念叫token撤銷,它容許咱們根據相同的受權許可以使特定的token甚至一組token無效。

5.5. JWT與OAuth的區別

  1. OAuth2是一種受權框架 ,JWT是一種認證協議
  2. 不管使用哪一種方式切記用HTTPS來保證數據的安全性
  3. OAuth2用在使用第三方帳號登陸的狀況(好比使用weibo, qq, github登陸某個app),而JWT是用在先後端分離, 須要簡單的對後臺API進行保護時使用。

5.6. 關於OAuth能夠參考下面幾篇

OAuth 2.0

Spring Security OAuth 2.0

OAuth 2.0 受權碼請求

6. 參考

https://jwt.io/

https://scotch.io/tutorials/the-ins-and-outs-of-token-based-authentication#toc-why-tokens-came-around

https://tools.ietf.org/html/rfc7519#section-3

http://blog.leapoahead.com/2015/09/06/understanding-jwt/

https://cnodejs.org/topic/557844a8e3cc2f192486a8ff

http://blog.leapoahead.com/2015/09/07/user-authentication-with-jwt/


歡迎各位轉載,但必須在文章頁面中給出做者和原文連接!
相關文章
相關標籤/搜索