mcpField
S
spring-boot-security-jwt

spring-boot-security-jwt

github.com/giuseppe-trisciuoglio安全3654.1k 次安装7 周前更新
代码仓库

关于 spring-boot-security-jwt

面向 Spring Boot 开发者的 JWT 安全实现技能,提供无状态认证、令牌轮换及细粒度授权模式。内容针对 Spring Security 6.x 和 JJWT。

主要功能

  1. 01访问令牌与刷新令牌生成和验证
  2. 02Bearer 与 HttpOnly Cookie 认证
  3. 03刷新令牌轮换、撤销与黑名单
  4. 04基于角色和权限的授权规则
  5. 05OAuth2 集成与安全测试

适用场景

  1. 01为 REST API 添加 JWT 认证
  2. 02实现登录、刷新和注销流程
  3. 03配置基于角色或权限的访问控制
  4. 04测试 Spring Security 配置

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill spring-boot-security-jwt

安装后在 Claude Code 中输入/spring-boot-security-jwt确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
generate-jwt-keys.sh
references/
authorization-patterns.md
configuration.md
examples.md
jwt-complete-configuration.md
jwt-configuration.md
jwt-quick-reference.md
jwt-testing-guide.md
microservices-security.md
migration-spring-security-6x.md
oauth2-integration.md
performance-optimization.md
security-hardening.md
structure.md
testing-jwt-security.md
testing.md
token-management.md
troubleshooting.md
scripts/
test-jwt-setup.sh

详细介绍

Spring Boot JWT 安全

适用于 Spring Boot 3.5.x、Spring Security 6.x 和 JJWT 的 JWT 身份验证与授权模式。涵盖令牌生成、验证、刷新策略、RBAC/ABAC 和 OAuth2 集成。

概述

此技能提供在 Spring Boot 应用中实现无状态 JWT 身份验证的模式。涵盖完整的身份验证流程,包括使用 JJWT 0.12.6 生成令牌、基于 Bearer/ Cookie 的身份验证、刷新令牌轮换,以及使用 @PreAuthorize 表达式进行方法级授权。

主要功能:

  • 生成具有可配置过期时间的访问令牌和刷新令牌
  • Bearer 令牌和 HttpOnly Cookie 身份验证策略
  • 与 Spring Data JPA 和 OAuth2 提供方集成
  • 基于角色/权限的 RBAC @PreAuthorize 规则
  • 用于注销/轮换的令牌撤销和黑名单

适用场景

在用户提出以下请求时启用:

  • “实现 JWT 身份验证”“使用令牌保护 REST API”
  • “Spring Security 6.x 配置”“设置 SecurityFilterChain”
  • “基于角色的访问控制”“RBAC”“`@PreAuthorize`”
  • “刷新令牌”“令牌轮换”“令牌撤销”
  • “OAuth2 集成”“社交登录”“Google/GitHub 身份验证”
  • “无状态身份验证”“SPA 后端安全”
  • “JWT 过滤器”“OncePerRequestFilter”“Bearer 令牌”
  • “基于 Cookie 的 JWT”“HttpOnly Cookie”
  • “基于权限的访问控制”“自定义 PermissionEvaluator”

快速参考

依赖项(JJWT 0.12.6)
构件作用域
spring-boot-starter-securitycompile
spring-boot-starter-oauth2-resource-servercompile
io.jsonwebtoken:jjwt-api:0.12.6compile
io.jsonwebtoken:jjwt-impl:0.12.6runtime
io.jsonwebtoken:jjwt-jackson:0.12.6runtime
spring-security-testtest

Maven 和 Gradle 代码片段请参阅 references/jwt-quick-reference.md。

关键配置属性
属性示例值说明
jwt.secret${JWT_SECRET}至少 256 位,切勿硬编码
jwt.access-token-expiration90000015 分钟,单位为毫秒
jwt.refresh-token-expiration6048000007 天,单位为毫秒
jwt.issuermy-app每次都验证
jwt.cookie-namejwt-token用于基于 Cookie 的身份验证
jwt.cookie-http-onlytrue生产环境中始终设为 true
jwt.cookie-securetrue使用 HTTPS 时始终设为 true
授权注解
注解示例
@PreAuthorize("hasRole('ADMIN')")角色检查
@PreAuthorize("hasAuthority('USER_READ')")权限检查
@PreAuthorize("hasPermission(#id, 'Doc', 'READ')")领域对象检查
@PreAuthorize("@myService.canAccess(#id)")Spring Bean 检查

操作说明

步骤 1 — 添加依赖项

在构建文件中加入 spring-boot-starter-security、spring-boot-starter-oauth2-resource-server 和三个 JJWT 构件。准确的 Maven/Gradle 代码片段请参阅 references/jwt-quick-reference.md。

步骤 2 — 配置 application.yml
jwt:
  secret: ${JWT_SECRET:change-me-min-32-chars-in-production}
  access-token-expiration: 900000
  refresh-token-expiration: 604800000
  issuer: my-app
  cookie-name: jwt-token
  cookie-http-only: true
  cookie-secure: false   # true in production

完整属性参考请参阅 references/jwt-complete-configuration.md。

步骤 3 — 实现 JwtService

核心操作:生成访问令牌、生成刷新令牌、提取用户名、验证令牌。

@Service
public class JwtService {

    public String generateAccessToken(UserDetails userDetails) {
        return Jwts.builder()
            .subject(userDetails.getUsername())
            .issuer(issuer)
            .issuedAt(new Date())
            .expiration(new Date(System.currentTimeMillis() + accessTokenExpiration))
            .claim("authorities", getAuthorities(userDetails))
            .signWith(getSigningKey())
            .compact();
    }

    public boolean isTokenValid(String token, UserDetails userDetails) {
        try {
            String username = extractUsername(token);
            return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
        } catch (JwtException e) {
            return false;
        }
    }
}

包含密钥管理和声明提取的完整 JwtService 请参阅 references/jwt-complete-configuration.md。

步骤 4 — 创建 JwtAuthenticationFilter

扩展 OncePerRequestFilter,从 Authorization: Bearer 标头(或 HttpOnly Cookie)中提取 JWT,验证令牌,并设置 SecurityContext。

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
            HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        String authHeader = request.getHeader("Authorization");
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            chain.doFilter(request, response);
            return;
        }
        String jwt = authHeader.substring(7);
        String username = jwtService.extractUsername(jwt);
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            if (jwtService.isTokenValid(jwt, userDetails)) {
                UsernamePasswordAuthenticationToken authToken =
                    new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authToken);
            }
        }
        chain.doFilter(request, response);
    }
}

基于 Cookie 的实现变体请参阅 references/configuration.md。

步骤 5 — 配置 SecurityFilterChain
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
            .csrf(AbstractHttpConfigurer::disable)
            .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/auth/**", "/swagger-ui/**").permitAll()
                .anyRequest().authenticated()
            )
            .authenticationProvider(authenticationProvider)
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
            .build();
    }
}

有关 CORS、注销处理器和 OAuth2 登录集成,请参阅 references/jwt-complete-configuration.md。

步骤 6 — 创建身份验证端点

通过 @RestController 暴露 /register、/authenticate、/refresh 和 /logout。在响应正文中返回 accessToken + refreshToken(也可以选择设置 HttpOnly Cookie)。

有关完整的 AuthenticationController 和 AuthenticationService,请参阅 references/examples.md。

步骤 7 — 实现刷新令牌策略

在数据库中存储刷新令牌,并使用 user_id、expiry_date、revoked 和 expired 列。在 /refresh 时,验证已存储的令牌,撤销该令牌,并签发一对新令牌(令牌轮换)。

有关 RefreshToken 实体、轮换逻辑和基于 Redis 的黑名单,请参阅 references/token-management.md。

步骤 8 — 添加授权规则

使用 @EnableMethodSecurity 和 @PreAuthorize 注解进行细粒度控制:

@PreAuthorize("hasRole('ADMIN')")
public Page<UserResponse> getAllUsers(Pageable pageable) { ... }

@PreAuthorize("hasPermission(#documentId, 'Document', 'READ')")
public Document getDocument(Long documentId) { ... }

有关 RBAC 实体模型、PermissionEvaluator 和 ABAC 模式,请参阅 references/authorization-patterns.md。

步骤 9 — 编写安全测试
@SpringBootTest
@AutoConfigureMockMvc
class AuthControllerTest {

    @Test
    void shouldDenyAccessWithoutToken() throws Exception {
        mockMvc.perform(get("/api/orders"))
            .andExpect(status().isUnauthorized());
    }

    @Test
    @WithMockUser(roles = "ADMIN")
    void shouldAllowAdminAccess() throws Exception {
        mockMvc.perform(get("/api/admin/users"))
            .andExpect(status().isOk());
    }
}

有关完整测试套件、Testcontainers 配置和安全测试清单,请参阅 references/testing.md 和 references/jwt-testing-guide.md。

最佳实践

令牌安全
  • 使用至少 256 位的密钥——从环境变量加载,切勿硬编码
  • 设置较短的访问令牌有效期(15 min);使用刷新令牌延长会话
  • 实现令牌轮换:签发新刷新令牌时撤销旧令牌
  • 使用 jti(JWT ID)声明,在注销时将令牌加入黑名单
Cookie 与 Bearer 标头
  • 对浏览器客户端优先使用 HttpOnly Cookie(可防范 XSS)
  • 对移动端/API 客户端使用 Authorization: Bearer 标头
  • 在生产环境中为 Cookie 设置 Secure、SameSite=Lax 或 Strict
Spring Security 6.x
  • 使用 SecurityFilterChain Bean——切勿扩展 WebSecurityConfigurerAdapter
  • 仅对无状态 API 禁用 CSRF;基于会话的流程应保持启用
  • 使用 @EnableMethodSecurity,而非已弃用的 @EnableGlobalMethodSecurity
  • 验证 iss 和 aud 声明;拒绝来自不受信任发行者的令牌
性能
  • 使用 @Cacheable 缓存 UserDetails,避免每次请求都查询数据库
  • 缓存签名密钥的派生结果(避免每次请求都重新计算 HMAC 密钥)
  • 大规模部署时使用 Redis 存储刷新令牌
不要做的事
  • 不要在 JWT 声明中存储敏感数据(密码、个人身份信息)——声明仅经过签名,并未加密
  • 不要签发有效期无限的令牌
  • 不要接受未经签名和有效期验证的令牌
  • 不要在不同环境之间共享签名密钥

示例

基本身份验证流程
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {

    private final AuthService authService;

    @PostMapping("/authenticate")
    public ResponseEntity<AuthResponse> authenticate(
            @RequestBody LoginRequest request) {
        return ResponseEntity.ok(authService.authenticate(request));
    }

    @PostMapping("/refresh")
    public ResponseEntity<AuthResponse> refresh(@RequestBody RefreshRequest request) {
        return ResponseEntity.ok(authService.refreshToken(request.refreshToken()));
    }

    @PostMapping("/logout")
    public ResponseEntity<Void> logout() {
        authService.logout();
        return ResponseEntity.ok().build();
    }
}
控制器方法中的 JWT 授权
@RestController
@RequestMapping("/api/admin")
@PreAuthorize("hasRole('ADMIN')")
public class AdminController {

    @GetMapping("/users")
    public ResponseEntity<List<UserResponse>> getAllUsers() {
        return ResponseEntity.ok(adminService.getAllUsers());
    }
}

有关完整的实体模型和服务实现,请参阅 references/examples.md。

参考资料

文件内容
references/jwt-quick-reference.md依赖、最简服务、常见模式
references/jwt-complete-configuration.md完整配置:属性、SecurityFilterChain、JwtService、OAuth2 RS
references/configuration.mdJWT 配置 Bean、CORS、CSRF、错误处理、会话选项
references/examples.md完整应用设置:控制器、服务、实体
references/authorization-patterns.mdRBAC/ABAC 实体模型、PermissionEvaluator、SpEL 表达式
references/token-management.md刷新令牌实体、轮换、使用 Redis 实现黑名单
references/testing.md单元测试和 MockMvc 测试、测试工具
references/jwt-testing-guide.mdTestcontainers、负载测试、安全测试清单
references/security-hardening.md安全头、HSTS、速率限制、审计日志
references/performance-optimization.mdCaffeine 缓存配置、异步验证、连接池
references/oauth2-integration.mdGoogle/GitHub OAuth2 登录、OAuth2UserService
references/microservices-security.md服务间 JWT 传递、资源服务配置
references/migration-spring-security-6x.md从 Spring Security 5.x 迁移
references/troubleshooting.md常见错误、调试技巧

限制和警告

安全限制
  • JWT 令牌经过签名但未加密 — 不要在声明中包含敏感数据
  • 在信任令牌之前,务必验证 exp、iss 和 aud 声明
  • 签名密钥必须至少为 256 位;生产环境中绝不能使用弱密钥
  • 从环境变量或安全保管库加载密钥,绝不要从配置文件加载
  • 基于 Cookie 的流程必须设置 SameSite Cookie 属性以防范 CSRF
Spring Security 6.x 限制
  • WebSecurityConfigurerAdapter 已移除 — 只能使用 SecurityFilterChain Bean
  • @EnableGlobalMethodSecurity 已弃用 — 使用 @EnableMethodSecurity
  • 配置 HttpSecurity 时必须使用 Lambda DSL(不能使用方法链式调用)
  • WebSecurityConfigurerAdapter.order() 已由 @Configuration 类上的 @Order 取代
令牌限制
  • 出于安全考虑,访问令牌的有效期应为 5-15 分钟
  • 刷新令牌应存储在服务端(数据库或 Redis),绝不能存储在 localStorage 中
  • 实现令牌黑名单,以便在注销时立即撤销令牌
  • 正确实现令牌黑名单需要 jti 声明

相关技能

  • spring-boot-dependency-injection — 全文使用的构造函数注入模式
  • spring-boot-rest-api-standards — REST API 安全模式和错误处理
  • unit-test-security-authorization — Spring Security 配置测试
  • spring-data-jpa — 用户实体和仓库模式
  • spring-boot-actuator — 安全监控和健康检查端点

评论

支持 Markdown