1. 程式人生 > 實用技巧 >五分鐘帶你瞭解啥是JWT

五分鐘帶你瞭解啥是JWT

1. JSON Web Token是什麼

JSON Web Token (JWT)是一個開放標準(RFC 7519),它定義了一種緊湊的、自包含的方式,用於作為JSON物件在各方之間安全地傳輸資訊。該資訊可以被驗證和信任,因為它是數字簽名的。

2. 什麼時候你應該用JSON Web Token

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

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

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

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

  • Header
  • Payload
  • Signature

因此,一個典型的JWT看起來是這個樣子的:

xxxxx.yyyyy.zzzzz

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

  • Header header典型的由兩部分組成:token的型別(“JWT”)和演算法名稱(比如:HMAC SHA256或者RSA等等)。

例如:

{
    'alg': "HS256",
    'typ': "JWT"
}

然後,用Base64對這個JSON編碼就得到JWT的第一部分

  • Payload JWT的第二部分是payload,它包含宣告(要求)。宣告是關於實體(通常是使用者)和其他資料的宣告。宣告有三種類型: registered, public 和 private。
    • Registered claims : 這裡有一組預定義的宣告,它們不是強制的,但是推薦。比如:iss (issuer), exp (expiration time), sub (subject), aud (audience)等。
    • Public claims : 可以隨意定義。
    • Private claims : 用於在同意使用它們的各方之間共享資訊,並且不是註冊的或公開的宣告。 下面是一個例子:
{
    "sub": '1234567890',
    "name": 'john',
    "admin":true
}

對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

伺服器上的受保護的路由將會檢查Authorization header中的JWT是否有效,如果有效,則使用者可以訪問受保護的資源。如果JWT包含足夠多的必需的資料,那麼就可以減少對某些操作的資料庫查詢的需要,儘管可能並不總是如此。

如果token是在授權頭(Authorization header)中傳送的,那麼跨源資源共享(CORS)將不會成為問題,因為它不使用cookie。

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中不會儲存任何使用者資訊。

沒有會話資訊意味著應用程式可以根據需要擴充套件和新增更多的機器,而不必擔心使用者登入的位置。

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

-使用者攜帶使用者名稱和密碼請求訪問 -伺服器校驗使用者憑據 -應用提供一個token給客戶端 -客戶端儲存token,並且在隨後的每一次請求中都帶著它 -伺服器校驗token並返回資料

注意:

-每一次請求都需要token -Token應該放在請求header中 -我們還需要將伺服器設定為接受來自所有域的請求,用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的區別 -OAuth2是一種授權框架 ,JWT是一種認證協議 -無論使用哪種方式切記用HTTPS來保證資料的安全性 -OAuth2用在使用第三方賬號登入的情況(比如使用weibo, qq, github登入某個app),而JWT是用在前後端分離, 需要簡單的對後臺API進行保護時使用