Spring Security
OWASP Top 10 Quick Rules
| Rule |
Critical Pattern |
| No hardcoded secrets |
@ConfigurationProperties + env vars / Vault |
| Parameterized queries |
.bind("param", value) -- never concatenate SQL |
| Validate all inputs |
@Valid @RequestBody + Bean Validation |
| JWT validation |
Verify signature + expiry; Keys.hmacShaKeyFor() |
| CORS locked down |
Explicit setAllowedOrigins(List.of("https://...")) |
| @JsonIgnore secrets |
On passwordHash, creditCard in all domain objects |
| Generic error messages |
Never expose stack traces, SQL errors, or keys |
| Rate limiting |
Every endpoint -- 100 req/min default, stricter for sensitive ops |
| File type whitelist |
Validate extension + magic bytes + size (max 5MB) |
| Path traversal |
resolved.startsWith(uploadDir) before file reads |
Security Config
MVC — SecurityFilterChain, HttpSecurity, OncePerRequestFilter for JWT, @EnableWebSecurity, @EnableMethodSecurity.
WebFlux — SecurityWebFilterChain, ServerHttpSecurity, @EnableWebFluxSecurity, @EnableReactiveMethodSecurity, oauth2ResourceServer with JWT converter.
Both: CSRF disabled (stateless), stateless sessions, explicit CORS origins (never *), BCrypt >= 12.
Secrets Management
@ConfigurationProperties with @Validated — map ${ENV_VAR} references
- Never hardcode secrets; never commit
application-local.yml
.gitignore: .env, *.pem, *.key, application-local.yml, application-secret.yml
- Production: Vault / AWS Secrets Manager / K8s Secrets
Pre-Deployment Checklist
Anti-Patterns
// BAD: SQL injection
String sql = "SELECT * FROM users WHERE name = '" + name + "'";
// GOOD: databaseClient.sql("SELECT ... WHERE name = :name").bind("name", name)
// BAD: Secret in code
private static final String API_KEY = "sk-proj-xxxx";
// GOOD: @Value("${app.api-key}") private String apiKey;
// BAD: Wildcard CORS
config.setAllowedOrigins(List.of("*"));
// GOOD: config.setAllowedOrigins(List.of("https://app.example.com"));
// BAD: Exposing internals
return new ErrorResponse(ex.getMessage(), ex.getStackTrace());
// GOOD: ProblemDetail.forStatusAndDetail(500, "An unexpected error occurred");
References
- references/jwt-auth.md — JWT filter (MVC), SecurityFilterChain, SecurityWebFilterChain, token provider, method security
- references/oauth2-oidc.md — OAuth2 resource server, client credentials, principal extraction, Spring Security 6.x migration, mockJwt()
- references/cors-headers.md — CORS (MVC + WebFlux), security headers filter
- references/security-testing.md — MockMvc + WebTestClient security tests, OWASP dep scanning
- references/file-upload-secrets.md — File upload validation, path traversal, secrets management
Related Skills
- redis-patterns — Redis-based rate limiting
- spring-webflux-patterns — Resilience4j rate limiting, WebFilter setup
- pentest — Security scanning, OWASP Top 10 assessment
- summer-security — APISIX auth, Keycloak integration (Summer projects)
1---2name: spring-security3description: Spring Security patterns — authentication, authorization, JWT, CORS, secrets management, OWASP scanning, security review for MVC and WebFlux applications. Use when configuring SecurityFilterChain or SecurityWebFilterChain, implementing JWT authentication, setting up CORS, applying method-level security, managing secrets, or reviewing OWASP compliance.4---56# Spring Security78## OWASP Top 10 Quick Rules910| Rule | Critical Pattern |11|------|-----------------|12| **No hardcoded secrets** | `@ConfigurationProperties` + env vars / Vault |13| **Parameterized queries** | `.bind("param", value)` -- never concatenate SQL |14| **Validate all inputs** | `@Valid @RequestBody` + Bean Validation |15| **JWT validation** | Verify signature + expiry; `Keys.hmacShaKeyFor()` |16| **CORS locked down** | Explicit `setAllowedOrigins(List.of("https://..."))` |17| **@JsonIgnore secrets** | On passwordHash, creditCard in all domain objects |18| **Generic error messages** | Never expose stack traces, SQL errors, or keys |19| **Rate limiting** | Every endpoint -- 100 req/min default, stricter for sensitive ops |20| **File type whitelist** | Validate extension + magic bytes + size (max 5MB) |21| **Path traversal** | `resolved.startsWith(uploadDir)` before file reads |2223## Security Config2425**MVC** — `SecurityFilterChain`, `HttpSecurity`, `OncePerRequestFilter` for JWT, `@EnableWebSecurity`, `@EnableMethodSecurity`.2627**WebFlux** — `SecurityWebFilterChain`, `ServerHttpSecurity`, `@EnableWebFluxSecurity`, `@EnableReactiveMethodSecurity`, `oauth2ResourceServer` with JWT converter.2829Both: CSRF disabled (stateless), stateless sessions, explicit CORS origins (never `*`), BCrypt >= 12.3031## Secrets Management3233- `@ConfigurationProperties` with `@Validated` — map `${ENV_VAR}` references34- Never hardcode secrets; never commit `application-local.yml`35- `.gitignore`: `.env`, `*.pem`, `*.key`, `application-local.yml`, `application-secret.yml`36- Production: Vault / AWS Secrets Manager / K8s Secrets3738## Pre-Deployment Checklist3940- [ ] No hardcoded secrets in source or git history41- [ ] JWT secret from env var; BCrypt cost >= 1242- [ ] CORS: explicit origins, no wildcards43- [ ] `@PreAuthorize` on sensitive methods44- [ ] `@Valid` on all request bodies; file upload whitelist45- [ ] Parameterized queries only (zero SQL concatenation)46- [ ] Rate limiting on auth + expensive endpoints47- [ ] Security headers: HSTS, X-Frame-Options, CSP, nosniff48- [ ] OWASP scan passes (`failBuildOnCVSS=7`)49- [ ] No PII/tokens/credentials in logs50- [ ] Actuator: only health/info public51- [ ] No `@Disabled` security tests5253## Anti-Patterns5455```java56// BAD: SQL injection57String sql = "SELECT * FROM users WHERE name = '" + name + "'";58// GOOD: databaseClient.sql("SELECT ... WHERE name = :name").bind("name", name)5960// BAD: Secret in code61private static final String API_KEY = "sk-proj-xxxx";62// GOOD: @Value("${app.api-key}") private String apiKey;6364// BAD: Wildcard CORS65config.setAllowedOrigins(List.of("*"));66// GOOD: config.setAllowedOrigins(List.of("https://app.example.com"));6768// BAD: Exposing internals69return new ErrorResponse(ex.getMessage(), ex.getStackTrace());70// GOOD: ProblemDetail.forStatusAndDetail(500, "An unexpected error occurred");71```7273## References7475- **[references/jwt-auth.md](references/jwt-auth.md)** — JWT filter (MVC), SecurityFilterChain, SecurityWebFilterChain, token provider, method security76- **[references/oauth2-oidc.md](references/oauth2-oidc.md)** — OAuth2 resource server, client credentials, principal extraction, Spring Security 6.x migration, mockJwt()77- **[references/cors-headers.md](references/cors-headers.md)** — CORS (MVC + WebFlux), security headers filter78- **[references/security-testing.md](references/security-testing.md)** — MockMvc + WebTestClient security tests, OWASP dep scanning79- **[references/file-upload-secrets.md](references/file-upload-secrets.md)** — File upload validation, path traversal, secrets management8081## Related Skills8283- **redis-patterns** — Redis-based rate limiting84- **spring-webflux-patterns** — Resilience4j rate limiting, WebFilter setup85- **pentest** — Security scanning, OWASP Top 10 assessment86- **summer-security** — APISIX auth, Keycloak integration (Summer projects)