Java实现JWT 双签发认证+RBAC权限的示例代码
作者:hqxstudying
本文主要介绍了Java实现JWT 双签发认证+RBAC权限的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
1. JWT 双签发认证基础概念
JWT(JSON Web Token)是一种用于在网络应用间传递声明的安全标准。双签发认证指的是同时签发访问令牌(Access Token)和刷新令牌(Refresh Token):
- Access Token:包含用户身份和权限信息,有效期较短(如 15 分钟)
- Refresh Token:仅包含用户身份信息,有效期较长(如 7 天)
- 当 Access Token 过期时,使用 Refresh Token 重新获取新的 Access Token
2. RBAC 权限模型基础概念
RBAC(基于角色的访问控制)是一种权限管理模型,核心组件包括:
- 用户(User):系统的使用者
- 角色(Role):一组权限的集合(如管理员、用户、访客)
- 权限(Permission):对资源的操作许可(如创建文章、删除用户)
- 用户 - 角色关联:一个用户可以拥有多个角色
- 角色 - 权限关联:一个角色可以包含多个权限
3. Java 项目中实现 JWT 双签发认证
以下是一个简单的 Java 实现示例,使用 Spring Security 和 JJWT 库:
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天 // 生成访问令牌 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(); } // 验证令牌 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 项目中实现 RBAC 权限控制
下面是一个基于 Spring Security 的 RBAC 实现示例:
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() // 认证接口不需要权限 .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. 数据库五层设计方案
一个完整的 RBAC 系统数据库设计通常包含以下五层:
第一层:用户层
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 );
第三层:权限层
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 );
第四层:关联层
-- 用户-角色关联表 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) ); -- 角色-权限关联表 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) );
第五层:资源层(可选,用于更细粒度控制)
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) ); -- 权限-资源关联表 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. 实现流程示例
以下是一个典型的认证授权流程:
- 用户登录,验证用户名密码
- 验证成功后,生成 Access Token 和 Refresh Token
- 将两个 Token 返回给客户端
- 客户端在请求头中携带 Access Token
- 服务端验证 Access Token 有效性
- 若 Access Token 过期,客户端使用 Refresh Token 请求新的 Access Token
- 服务端验证 Refresh Token,生成新的 Access Token 和 Refresh Token
- 服务端根据 Token 中的角色信息,结合 RBAC 权限控制进行访问控制
7. 安全增强建议
Refresh Token 存储安全:
- 考虑将 Refresh Token 存储在 HttpOnly Cookie 中,防止 XSS 攻击
- 对 Refresh Token 实现严格的同源策略
Token 泄露防护:
- 实现 Token 撤销机制
- 为每个用户维护一个唯一的设备标识
- 实现异常登录检测和通知
权限设计最佳实践:
- 遵循最小权限原则
- 定期审查和清理过时角色和权限
- 实现权限继承和权限组
到此这篇关于Java实现JWT 双签发认证+RBAC权限的示例代码的文章就介绍到这了,更多相关Java JWT 双签发认证+RBAC权限内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!