JSON Web Token在登陸中的使用過程
JWT(JSON Web Token)是一種開放標(biāo)準(zhǔn)(RFC 7519),用于在網(wǎng)絡(luò)應(yīng)用環(huán)境間安全地傳遞聲明。它的主要用途是身份驗(yàn)證和信息交換。
在微服務(wù)架構(gòu)中,JWT 作為認(rèn)證機(jī)制非常常見,特別是與 API 網(wǎng)關(guān)結(jié)合使用時。
JWT 介紹
JWT 是由三部分組成的:
- Header(頭部):通常包含簽名的算法信息(例如 HMAC SHA256 或 RSA)。
- Payload(負(fù)載):包含聲明(Claims)。聲明可以是關(guān)于實(shí)體(通常是用戶)的信息,或者元數(shù)據(jù)。JWT 的負(fù)載部分是 base64 編碼的。
- Signature(簽名):簽名是用來驗(yàn)證 JWT 數(shù)據(jù)是否被篡改的。它通過將 header 和 payload 使用私鑰加密生成,確保 JWT 的數(shù)據(jù)安全性和完整性。
微服務(wù)架構(gòu)中的 JWT 使用
在微服務(wù)架構(gòu)中,多個微服務(wù)通常會通過 HTTP 請求進(jìn)行交互。如果沒有合適的認(rèn)證機(jī)制,用戶的身份驗(yàn)證信息可能會在多個服務(wù)之間重復(fù)驗(yàn)證,這不但增加了冗余,也降低了安全性。
JWT 在這種情況下非常有用,因?yàn)樗茉谟脩舻卿洉r生成一個有效的 token,該 token 可以在不同的服務(wù)之間傳遞,而不需要每個服務(wù)都進(jìn)行用戶認(rèn)證。
結(jié)合微服務(wù)網(wǎng)關(guān)的 JWT 驗(yàn)證
微服務(wù)網(wǎng)關(guān)(如 Spring Cloud Gateway 或 Nginx)在微服務(wù)架構(gòu)中起到了流量管理、路由、負(fù)載均衡等作用。
JWT 與微服務(wù)網(wǎng)關(guān)結(jié)合時,網(wǎng)關(guān)通常扮演驗(yàn)證用戶身份的角色。
具體的流程如下:
流程示例
- 用戶登錄:用戶通過用戶名和密碼登錄。后端服務(wù)會驗(yàn)證這些憑證,如果驗(yàn)證成功,則生成一個 JWT token 返回給前端。
- 前端保存 JWT:前端將 JWT 保存在客戶端(如 localStorage 或 sessionStorage),并在后續(xù)的 API 請求中將其添加到 HTTP 請求的 Authorization 頭中。
- 微服務(wù)網(wǎng)關(guān)驗(yàn)證 JWT:用戶在每次請求時會將 JWT 發(fā)送到微服務(wù)網(wǎng)關(guān)。網(wǎng)關(guān)會驗(yàn)證 JWT 的有效性、簽名、過期時間等。如果 JWT 合法,則網(wǎng)關(guān)將請求轉(zhuǎn)發(fā)給目標(biāo)微服務(wù)。
- 微服務(wù)接收請求:微服務(wù)通過網(wǎng)關(guān)接收到請求時,已經(jīng)可以信任這個用戶的身份,無需再進(jìn)行身份驗(yàn)證。微服務(wù)可以從 JWT 的 Payload 中提取用戶信息來處理請求。
1. 用戶登錄,生成 JWT
public class JwtUtil {
private static final String SECRET_KEY = "secret"; // 用于加密的秘鑰
// 生成 JWT
public static String createJWT(String userName) {
return Jwts.builder()
.setSubject(userName)
.setIssuedAt(new Date()) // 設(shè)置發(fā)放時間
.setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 設(shè)置過期時間,1小時
.signWith(SignatureAlgorithm.HS256, SECRET_KEY) // 使用 HMAC-SHA256 加密
.compact();
}
// 解析 JWT
public static Claims parseJWT(String jwt) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(jwt)
.getBody();
}
}2. 自定義過濾器來實(shí)現(xiàn) JWT 的驗(yàn)證
@Component
public class JwtAuthenticationFilter implements GatewayFilter, Ordered {
private static final String AUTHORIZATION_HEADER = "Authorization";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst(AUTHORIZATION_HEADER);
if (token == null || !token.startsWith("Bearer ")) {
return Mono.error(new RuntimeException("Unauthorized"));
}
try {
String jwt = token.substring(7); // 去掉 "Bearer " 前綴
Claims claims = JwtUtil.parseJWT(jwt); // 解析 JWT
// 可以根據(jù)解析的 claims 來做進(jìn)一步的驗(yàn)證或設(shè)置安全上下文
exchange.getRequest().mutate()
.header("User", claims.getSubject()) // 在請求頭中設(shè)置用戶信息
.build();
} catch (Exception e) {
return Mono.error(new RuntimeException("Invalid token"));
}
return chain.filter(exchange); // 繼續(xù)處理請求
}
@Override
public int getOrder() {
return -1; // 優(yōu)先級,越小越優(yōu)先
}
}3. 微服務(wù)中使用 JWT 數(shù)據(jù)
微服務(wù)從網(wǎng)關(guān)接收到請求時,可以直接從請求頭中讀取用戶信息:
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/info")
public String getUserInfo(@RequestHeader("User") String userName) {
// 使用 userName 獲取用戶信息
return "Hello, " + userName;
}
}總結(jié)
通過將 JWT 和微服務(wù)網(wǎng)關(guān)結(jié)合使用,可以實(shí)現(xiàn)分布式系統(tǒng)中的統(tǒng)一身份驗(yàn)證。用戶登錄時通過 JWT 獲取認(rèn)證信息,網(wǎng)關(guān)負(fù)責(zé)驗(yàn)證 JWT 的有效性和用戶身份,然后將請求轉(zhuǎn)發(fā)到對應(yīng)的微服務(wù)。微服務(wù)無需再驗(yàn)證用戶身份,只需要從 JWT 中提取必要的用戶信息進(jìn)行業(yè)務(wù)處理。
這種方式有效地減少了重復(fù)認(rèn)證的開銷,同時提高了系統(tǒng)的安全性和可擴(kuò)展性。
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot啟動多數(shù)據(jù)源找不到合適的驅(qū)動類問題
這篇文章主要介紹了SpringBoot啟動多數(shù)據(jù)源找不到合適的驅(qū)動類問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01
IDEA2021.2配置docker如何將springboot項(xiàng)目打成鏡像一鍵發(fā)布部署
這篇文章主要介紹了IDEA2021.2配置docker如何將springboot項(xiàng)目打成鏡像一鍵發(fā)布部署,本文圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-09-09
Java 微信公眾號開發(fā)相關(guān)總結(jié)
公眾號作為主流的自媒體平臺,有著不少人使用。這次以文本回復(fù)作為案例來講解Java相關(guān)的微信公眾號開發(fā)2021-05-05
使用Java實(shí)現(xiàn)動態(tài)生成MySQL數(shù)據(jù)庫
這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)動態(tài)生成MySQL數(shù)據(jù)庫,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02
SpringBoot實(shí)現(xiàn)Word轉(zhuǎn)PDF和TXT的實(shí)踐分享
研發(fā)工作中難免會遇到一些奇奇怪怪的需求,就比如最近,客戶提了個新需求:上傳一個WORD文檔,要求通過系統(tǒng)把該文檔轉(zhuǎn)換成PDF和TXT,所以本文給大家分享了SpringBoot實(shí)現(xiàn)Word轉(zhuǎn)PDF和TXT的實(shí)踐,感興趣的朋友可以參考下2024-08-08

