一、前言

現在越來越多的專案或多或少會用到JWT,為什么會出現使用JWT這樣的場景的呢?
假設現在有一個APP,后臺是分布式系統,APP的首頁模塊部署在上海機房的服務器上,子頁面模塊部署在深圳機房的服務器上,此時你從首頁登錄了該APP,然后跳轉到子頁面模塊,session在兩個機房之間不能同步,用戶是否需要重新登錄?
傳統的方式(cookie+session)需要重新登錄,用戶體驗不好,session共享(在多臺物理機之間傳輸和復制session)方式對網路IO的壓力大,延遲太長,用戶體驗也不好,
說到這大家可能會想到,用服務器的session_id存盤到cookies中也能做到,為什么非要用token呢?網上有許多文章來比較token和session的優缺點,其實,開發web應用的話用哪種都行,但如果是開發api介面,前后端分離,最好使用token,為什么這么說呢,因為session+cookies是基于web的,但是針對 api介面,可能會考慮到移動端,app是沒有cookies和session的,
Session方式存盤用戶資訊的最大問題在于要占用大量服務器記憶體,增加服務器的開銷,
而JWT方式將用戶狀態分散到了客戶端中,可以明顯減輕服務端的記憶體壓力,Session的狀態是存盤在服務器端,客戶端只有session id;而Token的狀態是存盤在客戶端

二、原理
JSON Web Token(縮寫 JWT)

JWT 的原理是,服務器認證以后,生成一個 JSON 物件,發回給用戶,以后,用戶與服務端通信的時候,都要發回這個 JSON 物件,
服務器完全只靠這個物件認定用戶身份,為了防止用戶篡改資料,服務器在生成這個物件的時候,會加上簽名,
服務器就不保存任何 session 資料了,也就是說,服務器變成無狀態了,從而比較容易實作擴展,
三、組合
JWT 的三個部分依次是:Header(頭部)、Payload(負載)、Signature(簽名)
寫成一行,就是下面的樣子,
Header.Payload.Signature

一、Header
header典型的由兩部分組成:token的型別(“JWT”)和演算法名稱(比如:HMAC SHA256或者RSA等等)
{ "alg": "HS256", //alg屬性表示簽名的演算法(algorithm),默認是 HMAC SHA256(寫成 HS256) "typ": "JWT" //typ屬性表示這個令牌(token)的型別(type) }
然后用Base64對這個JSON編碼就得到JWT的第一部分
二、Payload
JWT的第二部分是payload,它包含宣告(要求),宣告是關于物體(通常是用戶)和其他資料的宣告
JWT 規定了7個官方欄位
- iss (issuer):簽發人
- exp (expiration time):過期時間
- sub (subject):主題
- aud (audience):受眾
- nbf (Not Before):生效時間
- iat (Issued At):簽發時間
- jti (JWT ID):編號
除了官方欄位,你還可以在這個部分定義私有欄位,下面就是一個例子
{ "sub": "1234567890", "name": "John Doe", "admin": true }
注意,不要在JWT的payload或header中放置敏感資訊,除非它們是加密的
三、Signature
Signature 部分是對前兩部分的簽名,防止資料篡改,簽名是用于驗證訊息在傳遞程序中有沒有被更改,并且,對于使用私鑰簽名的token,它還可以驗證JWT的發送方是否為它所稱的發送方,
為了得到簽名部分,你必須有編碼過的header、編碼過的payload、一個秘鑰,簽名演算法是header中指定的那個,然對它們簽名即可,按照下面的公式產生簽名,
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
算出簽名以后,把 Header、Payload、Signature 三個部分拼成一個字串,每個部分之間用"點"(.)分隔,就可以回傳給用戶,

四、開始
一、客戶端收到服務器回傳的 JWT,可以儲存在 Cookie 里面,也可以儲存在 localStorage,
此后,客戶端每次與服務器通信,都要帶上這個 JWT,你可以把它放在 Cookie 里面自動發送,但是這樣不能跨域,所以更好的做法是放在 HTTP 請求的頭資訊Authorization欄位里面,
Authorization: Bearer <token>
二、JWT 就放在 POST 請求的資料體里面,那么跨源資源共享(CORS)將不會成為問題,因為它不使用cookie

1.應用(或者客戶端)想授權服務器請求授權,例如,如果用授權碼流程的話,就是/oauth/authorize
2.當授權被許可以后,授權服務器回傳一個access token給應用
3.應用使用access token訪問受保護的資源(比如:API)
五、特點
1.JWT 默認是不加密,但也是可以加密的,生成原始 Token 以后,可以用密鑰再加密一次,
2.JWT 不加密的情況下,不能將秘密資料寫入 JWT,
3.JWT 的最大缺點是,由于服務器不保存 session 狀態,因此無法在使用程序中廢止某個 token,或者更改 token 的權限,也就是說,一旦 JWT 簽發了,在到期之前就會始終有效,除非服務器部署額外的邏輯,
4.JWT 本身包含了認證資訊,一旦泄露,任何人都可以獲得該令牌的所有權限,為了減少盜用,JWT 的有效期應該設定得比較短,對于一些比較重要的權限,使用時應該再次對用戶進行認證,
注意:
JWT 是 JSON 格式的被加密了的字串
JWT 的核心是密鑰,就是 JSON 資料,這是你關心的,并希望安全傳遞出去的資料,JWT 如何做到這一點,并使你信任它,就是加密簽名,

被篡改之后

六、總結
參考官方檔案:JSON Web Tokens
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/16055.html
標籤:ASP.NET
