JAVA后端開發—— JWT(JSON Web Token)實踐

1. 什么是HTTP請求頭 (Request Headers)?

當你的瀏覽器或手機App向服務器發起一個HTTP請求時,這個請求并不僅僅包含你要訪問的URL(比如?/logout)和可能的數據(請求體),它還附帶了一堆“元數據(Metadata)”,這些元數據就是請求頭

請求頭是一些鍵值對(Key-Value pairs),它們向服務器提供了關于本次請求的各種上下文信息,比如:

  • Host:?api.example.com?(我想訪問哪個服務器)

  • User-Agent:?Mozilla/5.0 ...?(我是用什么瀏覽器或設備發起的請求)

  • Accept:?application/json?(我希望你返回給我JSON格式的數據)

  • Content-Type:?application/json?(如果我發送了數據,那么這些數據的格式是JSON)

  • Authorization:?Bearer eyJhbGciOiJIUzI1Ni...?(這是身份憑證)

2. 為什么需要?Authorization?請求頭?

HTTP協議本身是無狀態的(Stateless)。這意味著服務器默認情況下,每一次收到請求,都把它當作一個全新的、陌生的請求來對待。它不會記得你上一次是誰,或者你是否已經登錄過。

為了解決這個問題,我們需要一種機制來讓客戶端在每次請求時都“自報家門”。Authorization?請求頭就是目前最主流的實現方式,特別是配合?Token-based Authentication(基于令牌的認證)

Token認證機制具有安全性。

  • 核心憑證只傳一次: 用戶的賬號密碼只在登錄那一次通過HTTPS安全地傳輸到服務器。

  • 暴露的是“臨時工”: Token是一個臨時的、可控的憑證。它本質上是服務器對“我信任這個客戶端”的一次授權聲明。即使Token在傳輸過程中被截獲,它的危害也是有限的

    • 有時效性: Token通常被設置為在幾小時或幾天后自動過期。攻擊者拿到一個過期的Token是完全沒用的。

    • 可被吊銷: 服務器可以建立一個“黑名單”機制。一旦發現某個Token泄露,可以立刻將其加入黑名單,使其立即失效。

    • 權限可控: Token的Payload(載荷)部分可以包含用戶的角色和權限信息。服務器可以簽發一個權限受限的Token(例如,一個只讀Token),即使泄露,攻擊者也無法執行寫操作。

3. 典型的登錄認證流程

  1. 登錄: 用戶提交用戶名和密碼到一個登錄接口(如?/login)。

  2. 獲取令牌 (Token): 服務器驗證用戶名和密碼成功后,生成一個加密的、有時效性的字符串,這個字符串就是令牌(Token)。服務器會將這個Token返回給客戶端。

  3. 客戶端存儲令牌: 客戶端(瀏覽器或App)收到Token后,會將其安全地存儲起來(比如在瀏覽器的?localStorage?或?sessionStorage?中)。

  4. 后續請求攜帶令牌: 從此以后,客戶端向服務器發起的每一個需要認證的請求,都必須在?Authorization?請求頭中附帶上這個Token。通常,Token前面還會加上一個Bearer的前綴,表示“持有者認證”。

  5. 服務器驗證令牌: 服務器收到請求后,會先檢查?Authorization?請求頭。如果存在,它會取出Token,對其進行解密和驗證(檢查簽名是否正確、是否過期等)。驗證通過后,服務器就知道了“哦,原來是張三發來的請求”,然后才繼續處理業務邏輯。

4.?Token的生命周期

  1. “生成”階段:?每一次獨立的登錄(Login)行為,都會觸發服務器生成一個全新的、不一樣的Token

  2. “使用”階段: 在某一次登錄成功后,直到這個Token過期或用戶手動登出之前,客戶端在發起每一次業務請求(Request)時,都會重復使用這同一個Token

5.JWT的“三段式”結構?

JWT Token而是由?三個部分?通過?.?連接而成的:

Header.Payload.Signature

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

  • 第一部分:Header (頭部)?eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

    • 內容: 描述這個JWT元信息的一個JSON對象,經過Base64Url編碼而成。

    • 解碼后:?{"alg": "HS256", "typ": "JWT"}

    • 含義:

      • alg: "HS256" (HMAC using SHA-256),聲明了簽名部分(Signature)使用的加密算法

      • typ: "JWT",聲明了這是一個JWT。

  • 第二部分:Payload (載荷)?eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

    • Payload?的設計初衷是用來存放與“用戶身份和權限”相關的、相對穩定的信息,這些信息在用戶的一次登錄會話中是不會改變的。

    • 內容: 包含了我們想傳遞的實際業務數據的一個JSON對象,也經過Base64Url編碼。

    • 解碼后:?{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}

    • 含義 (這里是一些標準字段):

      • sub: Subject (主題),通常存放用戶的唯一ID—— 這就是“判斷這個Token是誰的”關鍵!

      • name: 用戶名。

      • iat: Issued At (簽發時間),是一個時間戳。

      • exp: Expiration Time (過期時間),是一個時間戳。—— 這就是“檢查是否過期”的關鍵!

      • 注意: 任何人都可以對Header和Payload進行Base64Url解碼,看到里面的內容。所以,絕對不能在Payload中存放敏感信息,如密碼!

  • 第三部分:Signature (簽名)?SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

    • 內容: 這是一個加密后的字符串,是JWT安全性的核心。

    • 生成過程: 它是通過以下公式,使用在**服務器端秘密保存的一個密鑰(Secret Key)**生成的:
      HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secretKey )

    • 含義: 這個簽名就像是這份“聲明文件”(Header + Payload)的“數字指紋”或“防偽印章”。

6. 服務器驗證Token的全過程?

假設服務器收到一個HTTP請求,請求頭里有?Authorization: Bearer [一個JWT字符串]。在若依這類框架中,通常會有一個過濾器(Filter),比如?JwtAuthenticationTokenFilter,它會在請求到達你的Controller之前,自動執行以下驗證流程:

第1步:檢查請求頭,取出Token

這步很簡單,就是代碼層面的字符串操作。

第2步:解密和驗證(核心步驟)

這一步通常會由一個專門的JWT工具類(比如使用?jjwt?庫)來完成。validateToken(jwtToken)?方法內部會做以下事情:

a. 拆分Token

  • 將收到的?jwtToken?字符串,按?.?分割成三部分:headerPart,?payloadPart,?signaturePart。

b. 驗證簽名(Signature)—— 最關鍵的安全校驗

  • 服務器端有一個只有自己知道的、絕對保密的?secretKey。這個密鑰在項目啟動時就加載到內存中了。

  • 服務器會完全忽略收到的?signaturePart。

  • 它會用收到的?headerPart?和?payloadPart,以及自己保存在內存中的?secretKey重新計算一次簽名
    newSignature = HMACSHA256(headerPart + "." + payloadPart, mySecretKey)

  • 然后,它將?newSignature?與收到的?signaturePart?進行逐位比較

    • 如果兩者完全一致: 這證明了這個Token確實是由我(或擁有相同密鑰的其他可信服務)簽發的,并且?Header?和?Payload?在傳輸過程中沒有被任何人篡改過。因為只有持有?secretKey?才能生成出正確的簽名。——?驗證通過!

    • 如果兩者不一致: 這說明Token要么是偽造的,要么內容被篡改了。——?驗證失敗,立即拒絕請求!

c. 驗證載荷(Payload)—— 業務規則校驗

  • 在簽名驗證通過后,服務器才會信任?Payload?里的內容。

  • 它會對?payloadPart?進行Base64Url解碼,得到一個JSON對象。

  • 然后,它會檢查Payload中的標準聲明(Claims)

    • 檢查過期時間 (exp):?if (currentTime > payload.getExp()) { ... }

      • 獲取exp字段的值(一個時間戳)。

      • 與當前服務器時間進行比較。

      • 如果當前時間已經超過了exp時間,說明Token已過期。——?驗證失敗,拒絕請求!

    • 還可以檢查其他聲明,比如nbf?(Not Before,生效時間)等。

第3步:判斷這個Token是誰的,并建立會話上下文

在簽名和有效期都驗證通過后,現在服務器可以完全信任這個Token了。

a. 提取用戶信息

  • 服務器會從已經解碼的?Payload?中,提取出用戶的唯一標識,通常是?sub?(Subject) 字段。
    String userId = payload.get("sub");

  • 它還可能提取出角色、權限等其他信息。
    List<String> roles = payload.get("roles");

b. 建立安全上下文 (Security Context)

  • 現在服務器知道了:“這個合法請求是用戶?userId?發來的,他擁有?roles?這些角色。

  • 框架(如Spring Security)會創建一個認證對象(Authentication),把這些用戶信息封裝進去。

  • 然后,將這個認證對象存入一個**與當前線程綁定的“安全上下文”**中(SecurityContextHolder)。

c. 放行請求

  • 過濾器的工作到此完成,它會將請求放行,繼續傳遞給后續的過濾器,最終到達Controller方法。當請求最終到達Controller時,不再需要關心Token了。只需要從那個“安全上下文”中獲取用戶信息即可。?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/89797.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/89797.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/89797.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【SVM smote】MAP - Charting Student Math Misunderstandings

針對數據不平衡問題&#xff0c;用調整類別權重的方式來處理數據不平衡問題&#xff0c;同時使用支持向量機&#xff08;SVM&#xff09;模型進行訓練。 我們通過使用 SMOTE&#xff08;Synthetic Minority Over-sampling Technique&#xff09;進行過采樣&#xff0c;增加少數…

repmgr+pgbouncer實現對業務透明的高可用切換

本方案說明 PostgreSQL repmgr&#xff1a;實現主從自動故障檢測與切換&#xff08;Failover&#xff09;。PgBouncer&#xff1a;作為連接池&#xff0c;屏蔽后端數據庫變動&#xff0c;提供透明連接。動態配置更新&#xff1a;通過repmgr組件的promote_command階段觸發腳本…

查找服務器上存在線程泄露的進程

以下是一個改進的命令&#xff0c;可以列出所有線程數大于200的進程及其PID和線程數&#xff1a; find /proc -maxdepth 1 -type d -regex /proc/[0-9] -exec sh -c for pid_dir dopid$(basename "$pid_dir")if [ -f "$pid_dir/status" ]; thenthreads$(aw…

Facebook 開源多季節性時間序列數據預測工具:Prophet 飽和預測 Saturating Forecasts

文中內容僅限技術學習與代碼實踐參考&#xff0c;市場存在不確定性&#xff0c;技術分析需謹慎驗證&#xff0c;不構成任何投資建議。 Prophet 是一種基于加法模型的時間序列數據預測程序&#xff0c;在該模型中&#xff0c;非線性趨勢與年、周、日季節性以及節假日效應相匹配。…

從單線程到云原生:Redis 二十年演進全景與內在機理深剖

——從 1.0 到 7.2&#xff0c;一窺數據結構、網絡模型、持久化、復制、高可用與生態協同的底層脈絡&#xff08;一&#xff09;序章&#xff1a;為什么是 Redis 1999 年&#xff0c;Salvatore Sanfilippo 在開發一個實時訪客分析系統時&#xff0c;發現傳統磁盤型數據庫無法在…

得了甲亢軍隊文職體檢能過嗎

根據軍隊文職體檢現行標準&#xff0c;甲亢患者能否通過體檢需分情況判定&#xff0c;核心取決于病情控制狀態、治療結果及穩定時長。結合《軍隊選拔軍官和文職人員體檢通用標準》及補充規定&#xff0c;具體分析如下&#xff1a;?? 一、可直接通過體檢的情況臨床治愈滿1年且…

【編程語言】C、C++、C#深度對比:三種語言的演進歷程與應用場景

一、語言概述與歷史背景 &#xff08;一&#xff09;C語言&#xff1a;系統編程的基石誕生背景 1972年由Dennis Ritchie在貝爾實驗室開發為了重寫UNIX操作系統而創造從B語言演化而來&#xff0c;增加了數據類型設計目標&#xff1a;簡潔、高效、可移植設計哲學 “相信程序員”&…

《計算機網絡》實驗報告五 DNS協議分析與測量

目 錄 1、實驗目的 2、實驗環境 3、實驗內容 3.1 查看和配置本機的DNS系統 3.2 DNS信息測量 3.3 DNS協議分析 4、實驗結果與分析 4.1 查看和配置本機的DNS系統 4.2 DNS信息測量 4.3 DNS協議分析 5、實驗小結 5.1 問題與解決辦法&#xff1a; 5.2 心得體會&#x…

Python工廠方法模式詳解:從理論到實戰

一、工廠方法模式核心概念 工廠方法模式&#xff08;Factory Method Pattern&#xff09;是一種創建型設計模式&#xff0c;屬于經典23種設計模式之一。其核心思想是&#xff1a;定義一個創建對象的接口&#xff0c;但將具體對象的實例化過程延遲到子類中實現。這種模式通過引入…

python爬蟲獲取PDF

【前提&#xff1a;菜鳥學習的記錄過程&#xff0c;如果有不足之處&#xff0c;還請各位大佬大神們指教&#xff08;感謝&#xff09;】 1.方法一&#xff1a;網站找到目標數據【單篇PDF】 https://bidding.sinopec.com/tpfront/xxgg/004005/ 按F12&#xff0c;----檢查------…

IFN影視官網入口 - 4K影視在線看網站|網頁|打不開|下載

IFN影視是一個專注于影視內容的網站&#xff0c;提供電影、電視劇、綜藝等各類影視資源的在線觀看服務。該網站以用戶需求為導向&#xff0c;致力于為用戶提供高清、流暢的觀影體驗&#xff0c;并不斷更新內容以滿足不同用戶的觀看習慣和偏好。IFN影視的特色在于其內容豐富、分…

《計算機網絡》實驗報告四 TCP協議分析

目 錄 1、實驗目的 2、實驗環境 3、實驗內容 3.1 利用wget下載新疆大學主頁 3.2 使用wireshark分析TCP報文結構 3.3 使用wireshark分析建立連接的三次握手 3.4 使用wireshark分析釋放連接的四次揮手 4、實驗結果與分析 4.1 利用wget下載新疆大學主頁 4.2 使用wiresh…

知識 IP 的突圍:從 “靠感覺” 到 “系統 + AI” 的變現躍遷

越來越多的知識付費從業者陷入 “努力無成果” 的困局&#xff1a;做了內容、上了課程&#xff0c;卻沒人看、沒人買。核心問題不在于能力不足&#xff0c;而在于仍在用 “靠感覺” 的原始方式打造 IP。在流量內卷、節奏加快的當下&#xff0c;“內容情懷” 已撐不起一門生意&a…

4.Java創建對象有幾種方式?

1.使用 new 關鍵字&#xff08;最常用&#xff09;通過調用類的構造函數直接實例化對象Person person new Person(); // 調用無參構造 Person person new Person("Alice", 25); // 調用有參構造2.反射機制&#xff08;動態創建&#xff09;利用Java反射 API 在運行…

【好題】洛谷 P1600 [NOIP 2016 提高組] 天天愛跑步(倍增LCA+桶)

前言沒做出來&#xff0c;看了很多篇題解后AC了&#xff0c;感覺大部分題解講得不清楚。題目思路結果有兩種求法模擬跑步過程&#xff0c;統計每個節點能觀察到的人數考慮每條路徑會對哪些節點作出貢獻&#xff08;當前路徑的玩家能被觀察到&#xff09;嘗試第一種求法必須遍歷…

valkey之網絡管理架構深度解析

一、連接類型實現體系 valkey通過ConnectionType結構體構建了靈活的網絡連接抽象&#xff0c;支持多種連接類型的統一管理。每種連接類型都通過填充該結構體的函數指針來實現特定功能&#xff0c;形成了面向接口的設計模式。1.1 socket連接 Socket連接提供了最基礎的TCP/IP通信…

【解碼文本世界的“隱形分界線”:Windows與Linux回車換行之謎】

在計算機的文本世界里&#xff0c;回車&#xff08;Carriage Return&#xff0c;CR&#xff09;和換行&#xff08;Line Feed&#xff0c;LF&#xff09;是兩個看似簡單卻意義非凡的字符。它們如同文本中的“隱形分界線”&#xff0c;默默地劃分著段落與行&#xff0c;影響著文…

【Project】ELK 7.17.16 日志分析系統部署

ELK 日志分析系統集群部署 本文檔基于 Rocky Linux 9.4 系統&#xff0c;部署 ELK 7.17.16&#xff08;長期支持版&#xff09;集群 案例準備 1. 節點規劃IP主機名部署組件角色說明192.168.100.150kafka01Elasticsearch、Kibana主節點&#xff08;master&#xff09; 可視化192…

分布式定時任務系列13:死循環是任務觸發的銀彈?

傳送門 分布式定時任務系列1&#xff1a;XXL-job安裝 分布式定時任務系列2&#xff1a;XXL-job使用 分布式定時任務系列3&#xff1a;任務執行引擎設計 分布式定時任務系列4&#xff1a;任務執行引擎設計續 分布式定時任務系列5&#xff1a;XXL-job中blockingQueue的應用 …

Flutter基礎(前端教程①③-單例)

現實類比&#xff1a;公司打印機假設你們公司有一臺共享打印機&#xff1a;非單例&#xff08;重復創建&#xff09;&#xff1a;每個員工都自己買一臺打印機放在工位上結果&#xff1a;浪費錢&#xff0c;占空間&#xff0c;難維護單例&#xff08;唯一實例&#xff09;&#…