Java實現(xiàn)JWT令牌的示例代碼
一、簡介
JWT (JSON Web Token) 是一種 跨服務、跨語言的認證解決方案,常用于前后端分離項目(比如 Spring Boot + Vue)。
它的主要作用是:
- 身份認證
- 用戶登錄成功后,后端生成一個 JWT 返回給前端。
- 前端每次請求時帶上這個 JWT,后端根據(jù)它來確認“你是誰”。
- 無狀態(tài)認證(不依賴 session)
- 傳統(tǒng)的 session 登錄需要服務器保存狀態(tài),用戶多了容易占用大量內(nèi)存。
- JWT 是 自包含的,不需要服務器保存用戶狀態(tài),后端只要驗證 token 就行。
- 安全傳遞信息
- JWT 由三部分組成:Header.Payload.Signature。
- Payload 里可以存儲用戶 ID、角色、過期時間等信息。
- Signature 簽名部分保證 token 不會被篡改。
二、實現(xiàn)流程
- 用戶在 Vue 前端輸入用戶名、密碼 → 發(fā)送到 Spring Boot 登錄接口。
- Spring Boot 驗證賬號密碼成功后 → 生成 JWT → 返回給前端。
- Vue 將 JWT 保存(通常存在 localStorage 或 sessionStorage)。
- 前端每次請求后端 API 時,在請求頭 Authorization 里帶上:Authorization: Bearer <token>
- Spring Boot 攔截請求,驗證 JWT 是否有效:
- 簽名是否正確?
- 是否過期?
- 是否被篡改?
- 驗證通過才放行,否則返回 401(未認證)。
如圖:

三、實戰(zhàn)
這里我們用spring boot + vue 來演示,
在配置中:
# JWT #密鑰 注意密鑰要夠長58位 jwt.secret=abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+ #過期時間 jwt.expiration= 3600000
創(chuàng)建工具類:
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private long expiration; // 例如 3600000 = 1小時
// 生成 token
public String generateToken(String username) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + expiration);
return Jwts.builder()
.setSubject(username)
.setIssuedAt(now)
.setExpiration(expiryDate)
.signWith(Keys.hmacShaKeyFor(secret.getBytes()))
.compact();
}
// 獲取用戶名
public String getUsernameFromToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(Keys.hmacShaKeyFor(secret.getBytes()))
.build()
.parseClaimsJws(token)
.getBody()
.getSubject();
}
// 驗證 token
public boolean validateToken(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(Keys.hmacShaKeyFor(secret.getBytes()))
.build()
.parseClaimsJws(token);
return true;
} catch (JwtException | IllegalArgumentException e) {
return false;
}
}創(chuàng)建SecurityConfig文件
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
String path = exchange.getRequest().getURI().getPath();
// 1. 放行登錄注冊
if (path.startsWith("/user/login") || path.startsWith("/user/register") || path.startsWith("/chat-stream")) {
return chain.filter(exchange);
}
//如果沒有Authorization頭,返回401
if (!exchange.getRequest().getHeaders().containsKey("Authorization")) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
// 2. 處理Authorization頭
String authHeader = exchange.getRequest().getHeaders().getFirst("Authorization");
if (!authHeader.startsWith("Bearer ")) {
// 無有效Token,返回401
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
// 3. 解析Token
String token = authHeader.substring(7);
if (!jwtUtil.validateToken(token)) {
// Token驗證失?。ㄟ^期、簽名錯誤等),返回401并打印日志
System.out.println("JWT驗證失敗:Token無效或過期 - " + token);
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
// 4. Token有效,設置認證信息到安全上下文
String username = jwtUtil.getUsernameFromToken(token);
Authentication auth = new UsernamePasswordAuthenticationToken(
username, null, Collections.emptyList() // 無權限,可根據(jù)需求添加
);
// 5. 傳遞認證信息并繼續(xù)執(zhí)行過濾鏈
return chain.filter(exchange)
.contextWrite(ReactiveSecurityContextHolder.withAuthentication(auth));
}接著創(chuàng)建JwtFilter
@Autowired
private JwtUtil jwtUtil;
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
String path = exchange.getRequest().getURI().getPath();
// 1. 放行登錄注冊
if (path.startsWith("/user/login") || path.startsWith("/user/register") || path.startsWith("/chat-stream")) {
return chain.filter(exchange);
}
// 2. 處理Authorization頭
String authHeader = exchange.getRequest().getHeaders().getFirst("Authorization");
if (!authHeader.startsWith("Bearer ")) {
// 無有效Token,返回401
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
// 3. 解析Token
String token = authHeader.substring(7);
if (!jwtUtil.validateToken(token)) {
// Token驗證失敗(過期、簽名錯誤等),返回401并打印日志
System.out.println("JWT驗證失?。篢oken無效或過期 - " + token);
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
// 4. Token有效,設置認證信息到安全上下文
String username = jwtUtil.getUsernameFromToken(token);
Authentication auth = new UsernamePasswordAuthenticationToken(
username, null, Collections.emptyList() // 無權限,可根據(jù)需求添加
);
// 5. 傳遞認證信息并繼續(xù)執(zhí)行過濾鏈
return chain.filter(exchange)
.contextWrite(ReactiveSecurityContextHolder.withAuthentication(auth));
}在控制層中,我們就可以在登錄邏輯中創(chuàng)建、返回給密鑰了:
//生成token
String token = jwtUtil.generateToken(user.getUserName());
//封裝返回數(shù)據(jù)
HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put("token", token);在前端中,處理登錄請求,將登錄成功后后端返回的token保存到瀏覽器:
const onFinish = async (values) => {
loading.value = true
try {
if (isLogin.value) {
//加密數(shù)據(jù)
const encrypted = Encrypt(JSON.stringify(values))
// 實現(xiàn)登錄邏輯
const response = await request.post('/user/login', { data: encrypted })
//保存token
localStorage.setItem("token", JSON.parse(response.data).data.token)
alert("登錄成功")
// 刷新頁面
// window.location.reload()
} else {
//加密數(shù)據(jù)
const encrypted = Encrypt(JSON.stringify(values))
// 實現(xiàn)注冊邏輯
const response = await request.post('/user/register', { data: encrypted })
console.log('注冊:', values)
}
} catch (error) {
console.error(error)
alert("登錄失敗")
} finally {
loading.value = false
}
}創(chuàng)建request.Js,將保存到本地瀏覽器的token放到請求頭中:
import axios from "axios";
const request = axios.create({
baseURL: "/api",
timeout: 30000, // 修改為30秒
responseType: "stream" // 流式響應
});
// 請求攔截器:自動攜帶 token
request.interceptors.request.use(
(config) => {
const token = localStorage.getItem("token");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
export default request;發(fā)送請求:
// 刪除
const deleteChat = (id) => {
Modal.confirm({
title: '確認刪除',
content: '確定要刪除此對話嗎?(對話歷史也將會全部刪除)',
okText: '確認',
cancelText: '取消',
onOk() {
// 調用后端接口刪除對話
eventSource?.close();
request.delete(`/chat/delete/${id}`)
.then((response) => {
if (response.data.code === "200") {
//顯示更新成功
message.success('刪除成功');
//刷新對話列表
getChatList();
} else {
//顯示更新失敗
message.error('刪除失敗');
}
})
.catch(err => {
message.error('刪除失敗');
// console.error('刪除失敗:', err);
});
},
onCancel() {
console.log('取消刪除');
},
});
};運行可以看到,登錄成功后后端成功返回token:

Token成功保存:

如果token國企或者錯誤:

再次請求會顯示401無權限報錯

到此這篇關于Java實現(xiàn)JWT令牌的示例代碼的文章就介紹到這了,更多相關Java JWT令牌內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
SpringCloud中NacosNamingService的作用詳解
SpringCloud服務接口調用OpenFeign及使用詳解
Java如何獲取resources下的文件路徑和創(chuàng)建臨時文件

