Communitygithub.com

Spring Boot 安全审查

为 Java Spring Boot 服务提供认证/授权、输入验证、CSRF、密钥管理、安全头、速率限制和依赖安全方面的最佳实践。适用于审查 Spring Security 认证/授权、验证、CSRF、密钥、头信息或速率限制时使用。

Spring Boot 安全审查 是什么?

该技能为 Spring Boot 服务提供全面的安全审查指南,涵盖认证、授权、输入验证、CSRF 保护、密钥管理、安全头配置、CORS、速率限制和依赖安全。其核心原则是默认拒绝、验证输入、最小权限和安全配置优先。技能支持 JWT、OAuth2 和基于会话的认证,并通过 `@PreAuthorize` 和 `EnableMethodSecurity` 实现方法级授权。它强调使用 BCrypt 或 Argon2 进行密码哈希、使用 Bean Validation 进行输入验证,以及通过环境变量或 Vault 进行密钥外部化。该指南还包含了使用 Bucket4j 进行速率限制、使用 OWASP Dependency Check 进行依赖扫描,以及保护文件上传和 PII 日志记录。最后提供了一个发布前检查清单,以确保所有安全措施均已到位。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/springboot-security

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Spring Boot 安全审查 是做什么的?

在添加认证、处理输入、创建端点或处理密钥时使用。

何时激活

  • 添加认证(JWT、OAuth2、基于会话)
  • 实现授权(@PreAuthorize、基于角色的访问)
  • 验证用户输入(Bean Validation、自定义验证器)
  • 配置 CORS、CSRF 或安全头
  • 管理密钥(Vault、环境变量)
  • 添加速率限制或暴力破解保护
  • 扫描依赖的 CVE

认证

  • 首选无状态 JWT 或带有撤销列表的不透明令牌
  • 对会话使用 httpOnly、Secure、SameSite=Strict cookie
  • 使用 OncePerRequestFilter 或资源服务器验证令牌
@Component
public class JwtAuthFilter extends OncePerRequestFilter {
  private final JwtService jwtService;

  public JwtAuthFilter(JwtService jwtService) {
    this.jwtService = jwtService;
  }

  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
      FilterChain chain) throws ServletException, IOException {
    String header = request.getHeader(HttpHeaders.AUTHORIZATION);
    if (header != null && header.startsWith("Bearer ")) {
      String token = header.substring(7);
      Authentication auth = jwtService.authenticate(token);
      SecurityContextHolder.getContext().setAuthentication(auth);
    }
    chain.doFilter(request, response);
  }
}

授权

  • 启用方法安全:@EnableMethodSecurity
  • 使用 @PreAuthorize("hasRole('ADMIN')") 或 @PreAuthorize("@authz.canEdit(#id)")
  • 默认拒绝,仅暴露所需作用域
@RestController
@RequestMapping("/api/admin")
public class AdminController {

  @PreAuthorize("hasRole('ADMIN')")
  @GetMapping("/users")
  public List<UserDto> listUsers() {
    return userService.findAll();
  }

  @PreAuthorize("@authz.isOwner(#id, authentication)")
  @DeleteMapping("/users/{id}")
  public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
    userService.delete(id);
    return ResponseEntity.noContent().build();
  }
}

输入验证

  • 在控制器上使用 @Valid 进行 Bean Validation
  • 在 DTO 上应用约束:@NotBlank、@Email、@Size、自定义验证器
  • 渲染前使用白名单净化任何 HTML
// 错误:未验证
@PostMapping("/users")
public User createUser(@RequestBody UserDto dto) {
  return userService.create(dto);
}

// 正确:已验证的 DTO
public record CreateUserDto(
    @NotBlank @Size(max = 100) String name,
    @NotBlank @Email String email,
    @NotNull @Min(0) @Max(150) Integer age
) {}

@PostMapping("/users")
public ResponseEntity<UserDto> createUser(@Valid @RequestBody CreateUserDto dto) {
  return ResponseEntity.status(HttpStatus.CREATED)
      .body(userService.create(dto));
}

SQL 注入预防

  • 使用 Spring Data 仓库或参数化查询
  • 对于原生查询,使用 :param 绑定;切勿拼接字符串
// 错误:原生查询中的字符串拼接
@Query(value = "SELECT * FROM users WHERE name = '" + name + "'", nativeQuery = true)

// 正确:参数化原生查询
@Query(value = "SELECT * FROM users WHERE name = :name", nativeQuery = true)
List<User> findByName(@Param("name") String name);

// 正确:Spring Data 派生查询(自动参数化)
List<User> findByEmailAndActiveTrue(String email);

密码编码

  • 始终使用 BCrypt 或 Argon2 对密码进行哈希处理——切勿存储明文
  • 使用 PasswordEncoder Bean,不要手动哈希
@Bean
public PasswordEncoder passwordEncoder() {
  return new BCryptPasswordEncoder(12); // 成本因子 12
}

// 在服务中
public User register(CreateUserDto dto) {
  String hashedPassword = passwordEncoder.encode(dto.password());
  return userRepository.save(new User(dto.email(), hashedPassword));
}

CSRF 保护

  • 对于浏览器会话应用,保持 CSRF 启用;在表单/头中包含令牌
  • 对于使用 Bearer 令牌的纯 API,禁用 CSRF 并依赖无状态认证
http
  .csrf(csrf -> csrf.disable())
  .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS));

密钥管理

  • 源代码中不得包含密钥;从环境变量或 vault 加载
  • 保持 application.yml 不含凭据;使用占位符
  • 定期轮换令牌和数据库凭据
# 错误:硬编码在 application.yml 中
spring:
  datasource:
    password: mySecretPassword123

# 正确:环境变量占位符
spring:
  datasource:
    password: ${DB_PASSWORD}

# 正确:Spring Cloud Vault 集成
spring:
  cloud:
    vault:
      uri: https://vault.example.com
      token: ${VAULT_TOKEN}

安全头

http
  .headers(headers -> headers
    .contentSecurityPolicy(csp -> csp
      .policyDirectives("default-src 'self'"))
    .frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)
    .xssProtection(Customizer.withDefaults())
    .referrerPolicy(rp -> rp.policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.NO_REFERRER)));

CORS 配置

  • 在安全过滤器级别配置 CORS,而不是在每个控制器中
  • 限制允许的来源——在生产中切勿使用 *
@Bean
public CorsConfigurationSource corsConfigurationSource() {
  CorsConfiguration config = new CorsConfiguration();
  config.setAllowedOrigins(List.of("https://app.example.com"));
  config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
  config.setAllowedHeaders(List.of("Authorization", "Content-Type"));
  config.setAllowCredentials(true);
  config.setMaxAge(3600L);

  UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
  source.registerCorsConfiguration("/api/**", config);
  return source;
}

// 在 SecurityFilterChain 中:
http.cors(cors -> cors.configurationSource(corsConfigurationSource()));

速率限制

  • 对昂贵的端点应用 Bucket4j 或网关级限制
  • 记录并警报突发流量;返回 429 并附带重试提示
// 使用 Bucket4j 进行每端点速率限制
@Component
public class RateLimitFilter extends OncePerRequestFilter {
  private final Map<String, Bucket> buckets = new ConcurrentHashMap<>();

  private Bucket createBucket() {
    return Bucket.builder()
        .addLimit(Bandwidth.classic(100, Refill.intervally(100, Duration.ofMinutes(1))))
        .build();
  }

  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
      FilterChain chain) throws ServletException, IOException {
    String clientIp = request.getRemoteAddr();
    Bucket bucket = buckets.computeIfAbsent(clientIp, k -> createBucket());

    if (bucket.tryConsume(1)) {
      chain.doFilter(request, response);
    } else {
      response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
      response.getWriter().write("{\"error\": \"Rate limit exceeded\"}");
    }
  }
}

依赖安全

  • 在 CI 中运行 OWASP Dependency Check / Snyk
  • 保持 Spring Boot 和 Spring Security 在受支持的版本上
  • 在已知 CVE 上构建失败

日志记录和 PII

  • 切勿记录密钥、令牌、密码或完整的 PAN 数据
  • 对敏感字段进行脱敏;使用结构化 JSON 日志记录

文件上传

  • 验证大小、内容类型和扩展名
  • 存储在 web 根目录之外;如有必要进行扫描

发布前检查清单

  • 认证令牌已正确验证和过期
  • 每个敏感路径上都有授权守卫
  • 所有输入都已验证和净化
  • 没有字符串拼接的 SQL
  • CSRF 设置符合应用类型
  • 密钥已外部化;未提交任何密钥
  • 安全头已配置
  • API 上有速率限制
  • 依赖项已扫描且为最新
  • 日志中没有敏感数据

请记住:默认拒绝、验证输入、最小权限、安全优先配置。

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

相关技能