JAVA-JWT

JWT簡介??

????????JSON Web Token(JWT)是一個非常輕巧的規范,這個規范允許我們使用 JWT 在用戶和服務器之間傳遞安全可靠的信息。一個 JWT 實際上就是一個字符串,它由三部分組成,頭部、載荷與簽名。前兩部分需要經過 Base64 編碼,后一部分通過前兩部分 Base64 編碼后再加密而成。

????????JWT組成:Header + Payload + Signature

????????Header:頭部用于描述關于該 JWT 的最基本的信息,例如其類型以及簽名所用的算法等,如{"type":"JWT","alg":"HS256"},Base64 加密header后的字符串為(JWT官網JSON Web Tokens - jwt.io 可以驗證):eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

????????Payload:一般添加用戶的相關信息或其他業務需要的必要信息,但不建議添加敏感信息,因為該部分在客戶端可解密。如:{"id":"1","name":"張三","sex":"male"},Base64 加密Payload后的字符串為(JWT官網 可以驗證):eyJpZCI6IjEiLCJuYW1lIjoi5byg5LiJIiwic2V4IjoibWFsZSJ9

????????Signature:這個部分需要 Base64 加密后的 header 和 Base64 加密后的 payload 使用 “.” 連接組成的字符串,然后通過 header 中聲明的加密方式進行加鹽 salt組合加密,然后就構成了 jwt 的第三部分。如:salt設置為abc,Signature字符串為:mZKsezNd5e5Q0Gi4vdeyEH3-ilxG_qEHkZp0gn7ayr0

????????綜上,公式如下:

????????Token = Base64(Header).Base64(Payload).Base64(Signature)

????????Signature = Header指定的簽名算法(Base64(header).Base64(payload),秘鑰)

????????生成后的token信息為:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEiLCJuYW1lIjoi5byg5LiJIiwic2V4IjoibWFsZSJ9.mZKsezNd5e5Q0Gi4vdeyEH3-ilxG_qEHkZp0gn7ayr0

JWT應用

? ? ? ? 在分布式環境下,有狀態(含session)可以采用分布式session解決方案,參考:分布式session解決方案-CSDN博客,無狀態token+redis也可以實現分布式token驗證校驗,spring-session和token+redis 都借助了redis,如果實際項目不采用redis中間件,可以用JWT實現上述需求,架構示意圖如下:

? ? ? ? 項目中使用JWT步驟如下:

? ? ? ? 1、添加項目依賴:java-jwt

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.gingko</groupId><artifactId>jwt</artifactId><version>0.0.1-SNAPSHOT</version><name>jwt</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.7.6</spring-boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- jwt --><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>4.5.0</version></dependency><!-- fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.83</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><configuration><mainClass>com.gingko.jwt.JwtApplication</mainClass><skip>true</skip></configuration><executions><execution><id>repackage</id><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build></project>

? ? ? ? 2、編寫配置

# 應用服務 WEB 訪問端口
server:port: 8080#jwt key
jwt:key: gingko

? ? ? ? 3、代碼實現加密token,解密token。登錄成功后,將加密后的token返回到前臺,前臺放入本地緩存,請求后臺時,將token放入request header中,后臺通過攔截器實現token的校驗進而驗證用戶是否登錄,代碼如下:

? ? ? ? 后臺請求UserController:

package com.gingko.jwt.controller;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.gingko.jwt.common.GenericWebResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.util.Date;@RestController
@RequestMapping("/user")
public class UserController {@Value("${jwt.key}")private String jwtKey;@RequestMapping("/login")public GenericWebResult login(@RequestParam String userName,@RequestParam String password) {//到數據庫校驗通過Algorithm algorithm = Algorithm.HMAC256(jwtKey);String token = JWT.create().withClaim("userName",userName).withClaim("userId","001")//token半小時過期.withExpiresAt(new Date(System.currentTimeMillis() + 1800000)).sign(algorithm);return GenericWebResult.ok("登錄成功",token);}@RequestMapping("/getInfo")public GenericWebResult getInfo(@RequestAttribute String userId) {return GenericWebResult.ok("獲取信息成功 ",userId);}}

? ? ? ? 登錄攔截器LoginInterceptor:

package com.gingko.jwt.interceptor;
import com.alibaba.fastjson.JSON;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.gingko.jwt.common.GenericWebResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** 登錄攔截器*/
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {@Value("${jwt.key}")private String jwtKey;//登錄之前攔截@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String token = request.getHeader("token");response.setContentType("application/json");response.setCharacterEncoding("UTF-8");log.info("登錄校驗開始,token:{}", token);if (token == null || token.isEmpty()) {log.info("token為空,請求被攔截");response.setStatus(HttpStatus.UNAUTHORIZED.value());GenericWebResult genericWebResult = GenericWebResult.error("token為空,請求被攔截");String resultStr = JSON.toJSONString(genericWebResult);response.getWriter().write(resultStr);return false;}try {Algorithm algorithm = Algorithm.HMAC256(jwtKey);JWTVerifier verifier = JWT.require(algorithm).build();//驗證tokenDecodedJWT decodedJWT = verifier.verify(token);//將用戶id設置到request中request.setAttribute("userId",decodedJWT.getClaim("userId").asString());} catch (JWTVerificationException exception) {log.warn("token無效,請求被攔截");GenericWebResult genericWebResult = GenericWebResult.error("token無效,請求被攔截");String resultStr = JSON.toJSONString(genericWebResult);response.getWriter().write(resultStr);return false;}return true;}
}

? ? ? ? 配置類WebMvcConfig及統一返回值GenericWebResult

package com.gingko.jwt.config;
import com.gingko.jwt.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;/*** web配置類,配置攔截器*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Resourceprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/user/*").excludePathPatterns("/user/login");//登錄不用攔截}
}
package com.gingko.jwt.common;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/*** 向前臺返回的統一格式的結果*/
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class GenericWebResult {/*** 是否成功*/private boolean successFlag;/*** 成功或失敗返回的信息*/private String msg;/*** /*** 返回列表或樹形數據,用戶可以自由添加*/private Object property;/*** 數據總條數,分頁情況下使用*/private Long total;public static GenericWebResult ok() {return new GenericWebResult(true, null, null, null);}public static GenericWebResult ok(String msg) {return new GenericWebResult(true, msg, null, null);}public static GenericWebResult ok(Object property) {return new GenericWebResult(true, null, property, null);}public static GenericWebResult ok(String msg, Object property) {return new GenericWebResult(true, msg, property, null);}public static GenericWebResult ok(Object property, Long total) {return new GenericWebResult(true, null, property, total);}public static GenericWebResult ok(String msg, Object property, Long total) {return new GenericWebResult(true, msg, property, total);}public static GenericWebResult error(String msg) {return new GenericWebResult(false, msg, null, null);}public static GenericWebResult error(String msg, Object data) {return new GenericWebResult(false, msg, data, null);}
}

? ? ? ? 4、后臺啟動2個服務,端口分別是8080和8082,通過8080服務登錄,8082服務驗證token的有效性,篡改token后驗證token無效,符合預期。

?

?

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

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

相關文章

UI前端大數據處理挑戰與對策:保障數據安全與隱私

hello寶子們...我們是艾斯視覺擅長ui設計、前端開發、數字孿生、大數據、三維建模、三維動畫10年經驗!希望我的分享能幫助到您!如需幫助可以評論關注私信我們一起探討!致敬感謝感恩! 一、引言&#xff1a;大數據時代的前端安全新挑戰 在數字化轉型的浪潮中&#xff0c;前端已從…

DTO、VO、POJO與實體類使用方案(結合Mapper.xml)

結合MyBatis的Mapper.xml文件&#xff0c;展示完整的層級數據流轉和數據庫操作。 1. 實體類優化&#xff08;Entity&#xff09; // User.java Data NoArgsConstructor AllArgsConstructor TableName("sys_user") public class User {TableId(type IdType.AUTO)pr…

開源|VDBBench 1.0正式官宣,完全復刻業務場景,支持用戶自定義數據集

宣布個好消息&#xff0c;大家期待已久的VDBBench 1.0更新啦。 嘗鮮鏈接&#xff1a; https://github.com/zilliztech/VectorDBBench/releases/tag/v1.0.0 對于這個功能的更新&#xff0c;我們準備了很久&#xff0c;也思考了很多。 因為對我們來說&#xff0c;VDBBench 從來不…

7,FreeRTOS列表與列表項的插入刪除

一、實驗目標 創建三個動態任務&#xff0c;棧空間大小均為128字。startTask、Task1、Task2。startTask僅運行一次&#xff0c;負責task1、task2任務的創建&#xff0c;startTask任務的刪除。Task1負責初始化列表、列表項123&#xff0c;并進行列表項的插入實驗與刪除實驗。Tas…

兩款支持3D地圖的WebGIS框架對比

前言 在當前的WebGIS技術發展中&#xff0c;3D地形圖的可視化已經成為一個非常重要的功能&#xff0c;尤其是在城市規劃、環境監測和虛擬旅游等領域中的應用。對于開發者而言&#xff0c;選擇一個強大且適合的WebGIS框架是實現這些功能的關鍵。目前市場上較為流行的支持3D地形…

Github 2025-06-26 Go開源項目日報Top10

根據Github Trendings的統計,今日(2025-06-26統計)共有10個項目上榜。根據開發語言中項目的數量,匯總情況如下: 開發語言項目數量Go項目10PureBasic項目1使用Gitleaks保護和發現機密信息 創建周期:2203 天開發語言:Go協議類型:MIT LicenseStar數量:14645 個Fork數量:13…

C++實現魷魚、羊了個羊、掃雷、原神模擬

C++ 魷魚游戲模擬實現 魷魚游戲中的經典場景可以通過C++模擬實現,例如“紅綠燈”游戲。以下是一個簡化版本的核心代碼框架: #include <iostream> #include <thread> #include <chrono> #include <cstdlib> #include <ctime> #include <ve…

從用戶到權限:解密 AWS IAM Identity Center 的授權之道

大家好&#xff0c;今天我們來解決一個非常具體的實戰問題&#xff1a;如何讓 IAM Identity Center 中創建的用戶真正獲得 AWS 賬戶的操作權限&#xff0c;從而取代老舊的 IAM 用戶管理模式&#xff1f; 如果我們盯著用戶詳情頁&#xff0c;想找一個“附加角色”的按鈕&#x…

在 Spring Boot 中使用 MyBatis-Plus 的詳細教程

前言 在現代的 Java Web 開發中&#xff0c;Spring Boot 和 MyBatis 已經成為主流框架組合。為了提升開發效率和簡化數據庫操作&#xff0c;MyBatis-Plus&#xff08;簡稱 MP&#xff09;應運而生。它是一個 MyBatis 的增強工具&#xff0c;在 MyBatis 的基礎上只做增強不做改…

AI生成內容泛濫時代:從“袋鼠登機“視頻看AI鑒偽與游戲智能的未來

近年來&#xff0c;AI生成內容的質量突飛猛進&#xff0c;從文本到圖像再到視頻&#xff0c;幾乎達到了以假亂真的程度。近期一段"人類在飛機上吵架看呆袋鼠"的視頻在社交網絡瘋傳&#xff0c;獲得數千萬次觀看后&#xff0c;才被證實是AI生成內容&#xff0c;這一事…

為什么在linux中不能直接使用pip進行安裝

您好&#xff0c;這是一個非常深刻且關鍵的問題&#xff0c;觸及了 Linux 系統管理與 Python 開發實踐的核心原則。理解了這一點&#xff0c;您就真正開始像一位經驗豐富的開發者那樣思考了。 簡單來說&#xff0c;答案是&#xff1a;為了保護操作系統自身的穩定和完整性。 讓…

IDEA相關配置記錄

IDEA相關配置記錄 參考鏈接&#xff1a; 參考鏈接&#xff1a; 1、安裝jdk D:\Program Files\Java\jdk-21 https://blog.csdn.net/2302_81410974/article/details/142031416 2、安裝maven D:\Java\workspace-maven\apache-maven-3.9.10 . ├── LICENSE ├── NOTICE ├──…

FastGPT私有化部署完整指南

&#x1f680; FastGPT 私有化部署完整指南 &#x1f4cb; 環境要求 硬件要求 最低配置:CPU: 4核內存: 8GB存儲: 50GB網絡: 穩定互聯網連接推薦配置:CPU: 8核內存: 16GB存儲: 100GB SSD網絡: 10Mbps帶寬軟件環境 必需軟件:- Docker: > 20.10.0- Docker Compose: > 2.…

系統架構設計師論文分享-基于架構的軟件設計方法及應用

我的軟考歷程 摘要 2023年2月&#xff0c;我所在的公司做了開發紗線MES系統的決定&#xff0c;該系統為國內紗線工廠提供SAAS服務&#xff0c;旨在提高紗線工廠的智能化和數字化水平。我在該項目中被任命為系統架構設計師&#xff0c;全面掌管該項目的架構設計工作。本文將結…

團結引擎發布純鴻蒙應用

大家好&#xff0c;我是阿趙。 ??這里嘗試一下用團結引擎發布純鴻蒙系統的應用。 一、 安裝鴻蒙系統發布需要的組件 在團結引擎的Hub里面找到Add modules: 然后找到OpenHarmony的支持選項&#xff0c;由于我已經安裝過了&#xff0c;所以會顯示Installed&#xff0c;如果沒…

C++基礎(FreeRDP編譯)

安裝 先安裝openssl 保姆級OpenSSL下載及安裝教程,OpenSSL下載及安裝教程-CSDN博客 vcpkg integrate install 安裝 vcpkg install zlib vcpkg install ffmpeg:x64-windows 編譯指令 PS D:\freerdp\FreeRDP\build> cmake .. -G "Visual Studio 17 2022" -A x…

用celery作為信息中間件

要在 Django 的 settings.py 中設置 Redis 作為 Celery 的 broker 和(可選)backend,你需要添加如下配置: 安裝依賴(如未安裝): pip install celery redis在 settings.py 中添加 Celery 配置(推薦放在文件底部): # Celery 配置 CELERY_BROKER_URL = redis://127.0.0.1…

Postman介紹及使用

Postman 是一個強大的 API 開發、測試和文檔化工具&#xff0c;廣泛用于開發者、測試人員和 API 設計者。以下是 Postman 的核心使用指南&#xff0c;涵蓋基礎操作到進階功能&#xff1a; 一、基礎使用 安裝與界面 下載&#xff1a;官網下載&#xff08;支持 Windows/macOS/Lin…

Android14音頻子系統-ASoC-ALSA之DAPM電源管理子系統

文章目錄 概述1&#xff09;codec對象-WM89602&#xff09;ALSA下的kcontrol的構造與使用3&#xff09;ASOC-ALSA下的kcontrol構造與使用1、通用寄存器對象 - kcontrol2、DAPM下的寄存器對象-widget3、如何構造widget&#xff1f;4、抽象對象widget、route與path1&#xff09;r…

如何修改anaconda 創建新虛擬環境的路徑(默認是C:\.conda\envs)

參考文章&#xff1a; 如何修改anaconda 創建新虛擬環境的路徑(默認是C&#xff1a;\.conda\envs)_anaconda創建環境怎么改路徑-CSDN博客