springboot-security

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Spring Boot Security Review

Spring Boot Security 安全审查

Use when adding auth, handling input, creating endpoints, or dealing with secrets.
适用于添加认证、处理输入、创建端点或管理密钥的场景。

Authentication

认证

  • Prefer stateless JWT or opaque tokens with revocation list
  • Use
    httpOnly
    ,
    Secure
    ,
    SameSite=Strict
    cookies for sessions
  • Validate tokens with
    OncePerRequestFilter
    or resource server
java
@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);
  }
}
  • 优先使用带吊销列表的无状态JWT或不透明令牌
  • 会话使用
    httpOnly
    Secure
    SameSite=Strict
    类型的Cookie
  • 使用
    OncePerRequestFilter
    或资源服务器验证令牌
java
@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);
  }
}

Authorization

授权

  • Enable method security:
    @EnableMethodSecurity
  • Use
    @PreAuthorize("hasRole('ADMIN')")
    or
    @PreAuthorize("@authz.canEdit(#id)")
  • Deny by default; expose only required scopes
  • 启用方法级安全:
    @EnableMethodSecurity
  • 使用
    @PreAuthorize("hasRole('ADMIN')")
    @PreAuthorize("@authz.canEdit(#id)")
    注解
  • 默认拒绝所有请求,仅开放必要的权限范围

Input Validation

输入验证

  • Use Bean Validation with
    @Valid
    on controllers
  • Apply constraints on DTOs:
    @NotBlank
    ,
    @Email
    ,
    @Size
    , custom validators
  • Sanitize any HTML with a whitelist before rendering
  • 在控制器中结合
    @Valid
    使用Bean Validation
  • 在DTO上应用约束注解:
    @NotBlank
    @Email
    @Size
    或自定义验证器
  • 在渲染前使用白名单清理所有HTML内容

SQL Injection Prevention

SQL注入防护

  • Use Spring Data repositories or parameterized queries
  • For native queries, use
    :param
    bindings; never concatenate strings
  • 使用Spring Data仓库或参数化查询
  • 原生查询使用
    :param
    绑定;绝不要拼接字符串

CSRF Protection

CSRF防护

  • For browser session apps, keep CSRF enabled; include token in forms/headers
  • For pure APIs with Bearer tokens, disable CSRF and rely on stateless auth
java
http
  .csrf(csrf -> csrf.disable())
  .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
  • 对于基于浏览器会话的应用,保持CSRF启用;在表单或请求头中包含CSRF令牌
  • 对于使用Bearer令牌的纯API,禁用CSRF并依赖无状态认证
java
http
  .csrf(csrf -> csrf.disable())
  .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS));

Secrets Management

密钥管理

  • No secrets in source; load from env or vault
  • Keep
    application.yml
    free of credentials; use placeholders
  • Rotate tokens and DB credentials regularly
  • 源代码中不要存放密钥;从环境变量或密钥管理服务加载
  • application.yml
    中不要包含凭证;使用占位符
  • 定期轮换令牌和数据库凭证

Security Headers

安全头

java
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)));
java
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)));

Rate Limiting

限流

  • Apply Bucket4j or gateway-level limits on expensive endpoints
  • Log and alert on bursts; return 429 with retry hints
  • 对资源消耗大的端点使用Bucket4j或网关级限流
  • 对流量突发情况进行日志记录和告警;返回429状态码并附带重试提示

Dependency Security

依赖安全

  • Run OWASP Dependency Check / Snyk in CI
  • Keep Spring Boot and Spring Security on supported versions
  • Fail builds on known CVEs
  • 在CI流程中运行OWASP Dependency Check或Snyk
  • 保持Spring Boot和Spring Security为受支持的版本
  • 若存在已知CVE漏洞则终止构建

Logging and PII

日志与敏感数据

  • Never log secrets, tokens, passwords, or full PAN data
  • Redact sensitive fields; use structured JSON logging
  • 绝不要记录密钥、令牌、密码或完整的PAN数据
  • 对敏感字段进行脱敏;使用结构化JSON日志

File Uploads

文件上传

  • Validate size, content type, and extension
  • Store outside web root; scan if required
  • 验证文件大小、内容类型和扩展名
  • 存储在Web根目录之外;必要时进行扫描

Checklist Before Release

发布前检查清单

  • Auth tokens validated and expired correctly
  • Authorization guards on every sensitive path
  • All inputs validated and sanitized
  • No string-concatenated SQL
  • CSRF posture correct for app type
  • Secrets externalized; none committed
  • Security headers configured
  • Rate limiting on APIs
  • Dependencies scanned and up to date
  • Logs free of sensitive data
Remember: Deny by default, validate inputs, least privilege, and secure-by-configuration first.
  • 认证令牌已正确验证和过期
  • 每个敏感路径都有授权防护
  • 所有输入已验证和清理
  • 无字符串拼接的SQL语句
  • 根据应用类型正确配置CSRF策略
  • 密钥已外部化,无密钥提交到代码仓库
  • 已配置安全头
  • API已配置限流
  • 依赖已扫描且为最新版本
  • 日志中无敏感数据
注意:默认拒绝所有请求,验证所有输入,遵循最小权限原则,优先通过配置实现安全。