JWT詳解

一、什么是JWT

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

二、使用場景(來自理解JWT的使用場景和優劣

  • 一次性驗證:
    比如用戶注冊后需要發一封郵件讓其激活賬戶,通常郵件中需要有一個鏈接,這個鏈接需要具備以下的特性:能夠標識用戶,該鏈接具有時效性(通常只允許幾小時之內激活),不能被篡改以激活其他可能的賬戶…這種場景就和 jwt 的特性非常貼近,jwt 的 payload 中固定的參數:iss 簽發者和 exp 過期時間正是為其做準備的。
  • restful api的無狀態認證
    使用 jwt 來做 restful api 的身份認證也是值得推崇的一種使用方案。客戶端和服務端共享 secret;過期時間由服務端校驗,客戶端定時刷新;簽名信息不可被修改。spring security oauth jwt 提供了一套完整的 jwt 認證體系。

三、JWT結構

JWT由三部分組成,它們之間用圓點(.)連接。這三部分分別是:

  • Header
  • Payload
  • Signature

具體示例如下所示:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

3.1 Header

jwt的頭部由兩部分信息組成:

  • type:聲明類型,這里是jwt
  • alg:聲明加密的算法 通常直接使用 HMAC SHA256

完整的頭部信息如下:

{
  "type":"jwt",
  "alg":"HS256"
}

對頭部信息進行Base64編碼的得到第一部分的信息

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

3.2 Payload

載荷就是存放有效信息的地方,它包含聲明(要求)。聲明有三種類型:

  • registered claims:標準中注冊的聲明。這里有一組預定義的聲明,它們不是強制的,但是推薦
  • public claims:公共的聲明
  • private claims:私有的聲明

標準中注冊的聲明 (建議但不強制使用) :

  • iss: jwt簽發者
  • sub: jwt所面向的用戶
  • aud: 接收jwt的一方
  • exp: jwt的過期時間,這個過期時間必須要大于簽發時間
  • nbf: 定義在什么時間之前,該jwt都是不可用的
  • iat: jwt的簽發時間
  • jti: jwt的唯一身份標識,主要用來作為一次性token,從而回避重放攻擊

公共的聲明 :

公共的聲明可以添加任何的信息,一般添加用戶的相關信息或其他業務需要的必要信息.但不建議添加敏感信息,因為該部分在客戶端可解密.

私有的聲明 :

私有聲明是提供者和消費者所共同定義的聲明,一般不建議存放敏感信息,因為base64是對稱解密的,意味著該部分信息可以歸類為明文信息。

對Payload進行Base64加密就得到了JWT第二部分的內容。

3.3 signature

JWT的第三部分是一個簽證信息,這個簽證信息由三部分組成:

  • header (base64后的)
  • payload (base64后的)
  • secret

第三部分需要base64加密后的header和base64加密后的payload使用 . 連接組成的字符串,然后通過header中聲明的加密方式進行加鹽secret組合加密,然后就構成了JWT的第三部分。

注意:
secret是保存在服務器端的,JWT的簽發生成也是在服務器端的,secret就是用來進行JWT的簽發和JWT的驗證,所以,它就是你服務端的私鑰,在任何場景都不應該流露出去。一旦客戶端得知這個secret, 那就意味著客戶端是可以自我簽發JWT了。

四、JWT,OAuth2,Session對比

4.1 傳統的session認證

http協議本身是一種無狀態的協議,而這就意味著如果用戶向我們的應用提供了用戶名和密碼來進行用戶認證,那么下一次請求時,用戶還要再一次進行用戶認證才行,因為根據http協議,我們并不能知道是哪個用戶發出的請求,所以為了讓我們的應用能識別是哪個用戶發出的請求,我們只能在服務器存儲一份用戶登錄的信息,這份登錄信息會在響應時傳遞給瀏覽器,告訴其保存為cookie,以便下次請求時發送給我們的應用,這樣我們的應用就能識別請求來自哪個用戶了,這就是傳統的基于session認證。

但是這種基于session的認證使應用本身很難得到擴展,隨著不同客戶端用戶的增加,獨立的服務器已無法承載更多的用戶,而這時候基于session認證應用的問題就會暴露出來:

  • Session: 每個用戶經過我們的應用認證之后,我們的應用都要在服務端做一次記錄,以方便用戶下次請求的鑒別,通常而言session都是保存在內存中,而隨著認證用戶的增多,服務端的開銷會明顯增大
  • 擴展性: 用戶認證之后,服務端做認證記錄,如果認證的記錄被保存在內存中的話,這意味著用戶下次請求還必須要請求在這臺服務器上,這樣才能拿到授權的資源,這樣在分布式的應用上,相應的限制了負載均衡器的能力。這也意味著限制了應用的擴展能力
  • CSRF: 因為是基于cookie來進行用戶識別的, cookie如果被截獲,用戶就會很容易受到跨站請求偽造的攻擊

4.2 基于token的鑒權機制

JWT和OAuth2都是基于token的鑒權機制。基于token的鑒權機制類似于http協議也是無狀態的,它不需要在服務端去保留用戶的認證信息或者會話信息。這就意味著基于token認證機制的應用不需要去考慮用戶在哪一臺服務器登錄了,這就為應用的擴展提供了便利。

其基本的流程如下:

  1. 用戶使用用戶名密碼來請求服務器
  2. 服務器進行驗證用戶的信息
  3. 服務器通過驗證發送給用戶一個token
  4. 客戶端存儲token,并在每次請求時附送上這個token值
  5. 服務端驗證token值,并返回數據

這個token必須要在每次請求時傳遞給服務端,它應該保存在請求頭里, 另外,服務端要支持CORS(跨來源資源共享)策略,一般我們在服務端這么做就可以了Access-Control-Allow-Origin: *

4.3 JWT 認證協議與 OAuth2.0 授權框架不恰當比較(來自基于 Token 的 JWT 認證協議與 OAuth2.0 授權框架不恰當比較

之所以說是不恰當,是因為JWT和OAuth2是完全不通過的概念。既然 JWT 和 OAuth2 沒有可比性,為什么還要把這兩個放在一起說呢?很多情況下,在討論OAuth2的實現時,會把JSON Web Token作為一種認證機制使用。這也是為什么他們會經常一起出現。

  1. JWT 是一種認證協議
    JWT提供了一種用于發布接入令牌(Access Token),并對發布的簽名接入令牌進行驗證的方法。 令牌(Token)本身包含了一系列聲明,應用程序可以根據這些聲明限制用戶對資源的訪問。
  2. OAuth2 是一種授權框架
    OAuth2是一種授權框架,提供了一套詳細的授權機制。用戶或應用可以通過公開的或私有的設置,授權第三方應用訪問特定資源。
  3. JWT 使用場景
    JWT 的主要優勢在于使用無狀態、可擴展的方式處理應用中的用戶會話。服務端可以通過內嵌的聲明信息,很容易地獲取用戶的會話信息,而不需要去訪問用戶或會話的數據庫。在一個分布式的面向服務的框架中,這一點非常有用。但是,如果系統中需要使用黑名單實現長期有效的 Token 刷新機制,這種無狀態的優勢就不明顯了。
  • 優勢
    • 快速開發
    • 不需要 Cookie
    • JSON 在移動端的廣泛應用
    • 不依賴于社交登錄
    • 相對簡單的概念理解
  • 限制
    • Token有長度限制
    • Token不能撤銷
    • 需要 Token 有失效時間限制(exp)
  1. OAuth2 使用場景
    如果不介意API的使用依賴于外部的第三方認證提供者,你可以簡單地把認證工作留給認證服務商去做。也就是常見的,去認證服務商(比如 Facebook)那里注冊你的應用,然后設置需要訪問的用戶信息,比如電子郵箱、姓名等。當用戶訪問站點的注冊頁面時,會看到連接到第三方提供商的入口。用戶點擊以后被重定向到對應的認證服務商網站,獲得用戶的授權后就可以訪問到需要的信息,然后重定向回來。
  • 優勢
    • 快速開發
    • 實施代碼量小
    • 維護工作減少
    • 可以和 JWT 同時使用
    • 可針對不同應用擴展
  • 限制
    • 框架沉重
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,197評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,415評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,104評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,884評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,647評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,130評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,208評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,366評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,887評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,737評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,939評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,478評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,174評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,586評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,827評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,608評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,914評論 2 372

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,781評論 18 139
  • 一、預備知識 本文討論基于微服務架構下的身份認證和用戶授權的技術方案,在閱讀之前,最好先熟悉并理解以下幾個知識點:...
    mtide閱讀 66,702評論 10 321
  • 本文會詳細描述兩種通用的保證API安全性的方法:OAuth2和JSON Web Token (JWT) 假設: 你...
    恒宇少年閱讀 3,099評論 5 16
  • 1. 微服務架構介紹 1.1 什么是微服務架構? 形像一點來說,微服務架構就像搭積木,每個微服務都是一個零件,并使...
    靜修佛緣閱讀 6,659評論 0 39
  • 轉載本文需注明出處:微信公眾號EAWorld,違者必究。 本文目錄: 一、單體應用 VS 微服務 二、微服務常見安...
    72a1f772fe47閱讀 8,566評論 3 25