Spring Security: Authentifizierung, Autorisierung und Filterketten
Spring Security ist das Standardframework für Authentifizierung, Autorisierung und Schutzmechanismen in Spring-Anwendungen.
Fachliche Einordnung
Security ist kein Controller-Anhang, sondern eine Querschnittsarchitektur. Filterkette, SecurityContext, Method Security, Token und Session-Verhalten müssen bewusst gesetzt werden.
Enterprise-Merksatz: Spring Security ist das Standardframework für Authentifizierung, Autorisierung und Schutzmechanismen in Spring-Anwendungen.
Technische Darstellung
Kernkonzepte
- SecurityFilterChain als zentraler HTTP-Sicherheitsfluss.
- Authentication und Authorization getrennt denken.
- PasswordEncoder, CSRF, CORS und SessionCreationPolicy.
- Method Security mit @PreAuthorize.
- OAuth2 Resource Server für JWT-validierende APIs.
Wann einsetzen?
- Du schützt REST APIs, Web UIs oder Admin-Funktionen.
- Du validierst JWTs aus einem Identity Provider.
- Du brauchst Rollen, Scopes, Mandanten oder objektbezogene Regeln.
Typische Fehler und Risiken
- permitAll() zu breit setzen.
- CSRF in Browser-Flows deaktivieren ohne Grund.
- Rollen und Scopes uneinheitlich benennen.
- Fachliche Berechtigung nur im Frontend prüfen.
Legacy- und Modernisierungssicht
JAAS, container-managed security oder WebSphere Security werden auf SecurityFilterChain, OAuth2 Resource Server und Method Security abgebildet.
Ausführliches Beispiel
Das Beispiel zeigt bewusst nicht nur Annotationen, sondern auch die Verantwortung der Schicht. In echten Projekten sollte der technische Spring-Code an Adapter- oder Konfigurationsrändern bleiben, während die Fachlogik testbar und möglichst frameworkarm bleibt.
@Configuration
@EnableMethodSecurity
class SecurityConfiguration {
@Bean
SecurityFilterChain api(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable())
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/actuator/health").permitAll()
.requestMatchers(HttpMethod.POST, "/api/orders").hasAuthority("SCOPE_order.write")
.anyRequest().authenticated())
.oauth2ResourceServer(oauth -> oauth.jwt(Customizer.withDefaults()))
.build();
}
}
@Service
class OrderAdminService {
@PreAuthorize("hasAuthority('SCOPE_order.admin')")
public void cancelAnyOrder(UUID orderId) { /* fachliche Prüfung bleibt zusätzlich möglich */ }
}
Checkliste für Reviews
- Ist die Verantwortung des Bausteins klar: Framework steuert Lebenszyklus, Library wird gezielt benutzt?
- Ist die Fachlogik außerhalb von Controller, Listener, Repository-Implementierung oder Konfiguration?
- Sind Fehlerfälle, Timeouts, Security, Monitoring und Tests sichtbar modelliert?
- Gibt es klare Grenzen zwischen DTO, Domäne, Persistence und Infrastruktur?