Java實(shí)現(xiàn)JWT 雙簽發(fā)認(rèn)證+RBAC權(quán)限的示例代碼
1. JWT 雙簽發(fā)認(rèn)證基礎(chǔ)概念
JWT(JSON Web Token)是一種用于在網(wǎng)絡(luò)應(yīng)用間傳遞聲明的安全標(biāo)準(zhǔn)。雙簽發(fā)認(rèn)證指的是同時(shí)簽發(fā)訪問(wèn)令牌(Access Token)和刷新令牌(Refresh Token):
- Access Token:包含用戶身份和權(quán)限信息,有效期較短(如 15 分鐘)
- Refresh Token:僅包含用戶身份信息,有效期較長(zhǎng)(如 7 天)
- 當(dāng) Access Token 過(guò)期時(shí),使用 Refresh Token 重新獲取新的 Access Token
2. RBAC 權(quán)限模型基礎(chǔ)概念
RBAC(基于角色的訪問(wèn)控制)是一種權(quán)限管理模型,核心組件包括:
- 用戶(User):系統(tǒng)的使用者
- 角色(Role):一組權(quán)限的集合(如管理員、用戶、訪客)
- 權(quán)限(Permission):對(duì)資源的操作許可(如創(chuàng)建文章、刪除用戶)
- 用戶 - 角色關(guān)聯(lián):一個(gè)用戶可以擁有多個(gè)角色
- 角色 - 權(quán)限關(guān)聯(lián):一個(gè)角色可以包含多個(gè)權(quán)限
3. Java 項(xiàng)目中實(shí)現(xiàn) JWT 雙簽發(fā)認(rèn)證
以下是一個(gè)簡(jiǎn)單的 Java 實(shí)現(xiàn)示例,使用 Spring Security 和 JJWT 庫(kù):
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
@Component
public class JwtUtil {
private static final String SECRET_KEY = "your-secret-key";
private static final long ACCESS_TOKEN_VALIDITY = 15 * 60 * 1000; // 15分鐘
private static final long REFRESH_TOKEN_VALIDITY = 7 * 24 * 60 * 60 * 1000; // 7天
// 生成訪問(wèn)令牌
public String generateAccessToken(String username, String roles) {
Map<String, Object> claims = new HashMap<>();
claims.put("roles", roles);
return createToken(claims, username, ACCESS_TOKEN_VALIDITY);
}
// 生成刷新令牌
public String generateRefreshToken(String username) {
return createToken(new HashMap<>(), username, REFRESH_TOKEN_VALIDITY);
}
private String createToken(Map<String, Object> claims, String subject, long validity) {
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + validity))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
// 驗(yàn)證令牌
public Boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}
// 從令牌中獲取用戶名
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
// 從令牌中獲取角色
public String getRolesFromToken(String token) {
return (String) getAllClaimsFromToken(token).get("roles");
}
private <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
}
}4. Java 項(xiàng)目中實(shí)現(xiàn) RBAC 權(quán)限控制
下面是一個(gè)基于 Spring Security 的 RBAC 實(shí)現(xiàn)示例:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
private final JwtRequestFilter jwtRequestFilter;
public SecurityConfig(JwtRequestFilter jwtRequestFilter) {
this.jwtRequestFilter = jwtRequestFilter;
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll() // 認(rèn)證接口不需要權(quán)限
.antMatchers("/api/admin/**").hasRole("ADMIN") // 需要ADMIN角色
.antMatchers("/api/user/**").hasAnyRole("ADMIN", "USER") // 需要ADMIN或USER角色
.anyRequest().authenticated()
.and()
.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}5. 數(shù)據(jù)庫(kù)五層設(shè)計(jì)方案
一個(gè)完整的 RBAC 系統(tǒng)數(shù)據(jù)庫(kù)設(shè)計(jì)通常包含以下五層:
第一層:用戶層
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
status TINYINT NOT NULL DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);第二層:角色層
CREATE TABLE roles (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
role_name VARCHAR(50) UNIQUE NOT NULL,
description VARCHAR(255),
status TINYINT NOT NULL DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);第三層:權(quán)限層
CREATE TABLE permissions (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
permission_name VARCHAR(50) UNIQUE NOT NULL,
description VARCHAR(255),
status TINYINT NOT NULL DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);第四層:關(guān)聯(lián)層
-- 用戶-角色關(guān)聯(lián)表
CREATE TABLE user_roles (
user_id BIGINT NOT NULL,
role_id BIGINT NOT NULL,
PRIMARY KEY (user_id, role_id),
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (role_id) REFERENCES roles(id)
);
-- 角色-權(quán)限關(guān)聯(lián)表
CREATE TABLE role_permissions (
role_id BIGINT NOT NULL,
permission_id BIGINT NOT NULL,
PRIMARY KEY (role_id, permission_id),
FOREIGN KEY (role_id) REFERENCES roles(id),
FOREIGN KEY (permission_id) REFERENCES permissions(id)
);第五層:資源層(可選,用于更細(xì)粒度控制)
CREATE TABLE resources (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
resource_name VARCHAR(50) UNIQUE NOT NULL,
resource_type VARCHAR(50) NOT NULL,
parent_id BIGINT,
url VARCHAR(255),
status TINYINT NOT NULL DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (parent_id) REFERENCES resources(id)
);
-- 權(quán)限-資源關(guān)聯(lián)表
CREATE TABLE permission_resources (
permission_id BIGINT NOT NULL,
resource_id BIGINT NOT NULL,
actions VARCHAR(100) NOT NULL, -- 如: "create,read,update,delete"
PRIMARY KEY (permission_id, resource_id),
FOREIGN KEY (permission_id) REFERENCES permissions(id),
FOREIGN KEY (resource_id) REFERENCES resources(id)
);6. 實(shí)現(xiàn)流程示例
以下是一個(gè)典型的認(rèn)證授權(quán)流程:
- 用戶登錄,驗(yàn)證用戶名密碼
- 驗(yàn)證成功后,生成 Access Token 和 Refresh Token
- 將兩個(gè) Token 返回給客戶端
- 客戶端在請(qǐng)求頭中攜帶 Access Token
- 服務(wù)端驗(yàn)證 Access Token 有效性
- 若 Access Token 過(guò)期,客戶端使用 Refresh Token 請(qǐng)求新的 Access Token
- 服務(wù)端驗(yàn)證 Refresh Token,生成新的 Access Token 和 Refresh Token
- 服務(wù)端根據(jù) Token 中的角色信息,結(jié)合 RBAC 權(quán)限控制進(jìn)行訪問(wèn)控制
7. 安全增強(qiáng)建議
Refresh Token 存儲(chǔ)安全:
- 考慮將 Refresh Token 存儲(chǔ)在 HttpOnly Cookie 中,防止 XSS 攻擊
- 對(duì) Refresh Token 實(shí)現(xiàn)嚴(yán)格的同源策略
Token 泄露防護(hù):
- 實(shí)現(xiàn) Token 撤銷機(jī)制
- 為每個(gè)用戶維護(hù)一個(gè)唯一的設(shè)備標(biāo)識(shí)
- 實(shí)現(xiàn)異常登錄檢測(cè)和通知
權(quán)限設(shè)計(jì)最佳實(shí)踐:
- 遵循最小權(quán)限原則
- 定期審查和清理過(guò)時(shí)角色和權(quán)限
- 實(shí)現(xiàn)權(quán)限繼承和權(quán)限組
到此這篇關(guān)于Java實(shí)現(xiàn)JWT 雙簽發(fā)認(rèn)證+RBAC權(quán)限的示例代碼的文章就介紹到這了,更多相關(guān)Java JWT 雙簽發(fā)認(rèn)證+RBAC權(quán)限內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot實(shí)現(xiàn)token驗(yàn)證登陸狀態(tài)的示例代碼
本文主要介紹了spring?boot?實(shí)現(xiàn)token驗(yàn)證登陸狀態(tài),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-07-07
java讀取某個(gè)文件夾下的所有文件實(shí)例代碼
這篇文章主要介紹了java讀取某個(gè)文件夾下的所有文件實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03
Java SpringBoot 使用攔截器作為權(quán)限控制的實(shí)現(xiàn)方法
這篇文章主要介紹了Java SpringBoot 使用攔截器作為權(quán)限控制的實(shí)現(xiàn),文中通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-10-10
Java應(yīng)用注冊(cè)成Windows服務(wù)實(shí)現(xiàn)自啟的教程詳解
這篇文章主要給大家介紹了Java應(yīng)用注冊(cè)成Windows服務(wù)實(shí)現(xiàn)自啟的教程,文中有詳細(xì)的代碼示例和圖文講解供大家參考,具有一定的參考價(jià)值,需要的朋友可以參考下2024-02-02
java實(shí)現(xiàn)轉(zhuǎn)圈打印矩陣算法
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)轉(zhuǎn)圈打印矩陣算法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-03-03
SpringMVC異常全局捕獲與錯(cuò)誤響應(yīng)的處理方法
編程式異常處理是通過(guò)在代碼中?顯式編寫異常捕獲邏輯(如?try-catch?塊)來(lái)管理異常的方式,開(kāi)發(fā)者需要手動(dòng)處理每一個(gè)可能拋出異常的代碼段,本文給大家介紹SpringMVC異常全局捕獲與錯(cuò)誤響應(yīng)的處理方法,感興趣的朋友一起看看吧2025-03-03
淺談Spring Cloud zuul http請(qǐng)求轉(zhuǎn)發(fā)原理
這篇文章主要介紹了淺談Spring Cloud zuul http請(qǐng)求轉(zhuǎn)發(fā)原理,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
使用VS?Code進(jìn)行java開(kāi)發(fā)與調(diào)試的圖文教程
這篇文章主要介紹了如何在計(jì)算機(jī)上安裝JDK、VSCode以及Java擴(kuò)展包,并詳細(xì)說(shuō)明了配置Java運(yùn)行環(huán)境的過(guò)程,還展示了如何在VSCode中新建一個(gè)Java項(xiàng)目,需要的朋友可以參考下2025-02-02
springboot3.x版本集成log4j沖突以及解決log4j沖突不生效問(wèn)題
由于Spring Boot自帶的Logback與Log4j沖突,去除了Logback的jar包后仍存在,原因是其他包也引入了Logback,解決方法是找到并去除引入Logback的其他包,如actuator包,并更新Maven2024-11-11

