天天看點

jwt如何防止token被竊取_五分鐘帶你了解啥是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等等)。

例如:

然後,用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的發送方是否為它所稱的發送方。

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

jwt如何防止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的狀态是存儲在用戶端。

jwt如何防止token被竊取_五分鐘帶你了解啥是JWT

5.3. 基于Token的身份認證是如何工作的 基于Token的身份認證是無狀态的,伺服器或者Session中不會存儲任何使用者資訊。

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

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

-使用者攜帶使用者名和密碼請求通路 -伺服器校驗使用者憑據 -應用提供一個token給用戶端 -用戶端存儲token,并且在随後的每一次請求中都帶着它 -伺服器校驗token并傳回資料

注意:

-每一次請求都需要token -Token應該放在請求header中 -我們還需要将伺服器設定為接受來自所有域的請求,用Access-Control-Allow-Origin: *

jwt如何防止token被竊取_五分鐘帶你了解啥是JWT

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進行保護時使用。