Security: AuthN, AuthZ, OAuth2, JWT und Secrets

Sicherheit als Architekturquerschnitt statt späteres Add-on.

Enterprise JavaBeispieleArchitekturOffline HTML

Security-Grundmodell

Enterprise Security besteht aus mehreren Schichten: Transport-Sicherheit, Authentifizierung, Autorisierung, Eingabevalidierung, Secret Management, Audit, sichere Defaults und Dependency-Sicherheit. Ein Framework kann vieles bereitstellen, aber die fachlichen Rechte und Datenzugriffe muss das Team modellieren.

BegriffBedeutungTypischer Fehler
AuthenticationWer bist du?Login vorhanden, aber Token nicht validiert
AuthorizationWas darfst du?Nur Rollen auf Endpunkt, keine Objekt-/Mandantenprüfung
OAuth2/OIDCDelegierte Autorisierung / LoginFrontend-Flow und Service-to-Service-Flow vermischen
JWTtragbares Token mit ClaimsClaims blind vertrauen ohne Signatur/Audience/Issuer-Prüfung
SecretsPasswörter, Keys, TokensSecrets in Git, Dockerfile oder Logs

Spring Security Resource Server

OAuth2 Resource Server Konfiguration
@Bean
SecurityFilterChain apiSecurity(HttpSecurity http) throws Exception {
    return http
        .authorizeHttpRequests(auth -> auth
            .requestMatchers(HttpMethod.GET, "/actuator/health").permitAll()
            .requestMatchers("/api/admin/**").hasAuthority("SCOPE_admin")
            .requestMatchers("/api/orders/**").hasAuthority("SCOPE_orders")
            .anyRequest().authenticated())
        .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
        .csrf(csrf -> csrf.disable())
        .build();
}
Mandantenregel: Rollen reichen selten. Bei /customers/ muss geprüft werden, ob der Benutzer genau diesen Kunden sehen darf.

Security im Code nicht verstreuen

Policy Object für fachliche Autorisierung
public class CustomerAccessPolicy {
    // Pattern: Policy Object - fachliche Zugriffsregel ist testbar und nicht in Controller verstreut.
    public boolean canReadCustomer(UserPrincipal user, CustomerId customerId) {
        return user.hasScope("customers:read") &&
               (user.isEmployee() || user.customerIds().contains(customerId));
    }
}
⌂ Cockpit