Woche 6, Tag 4 — CSRF, CORS, Sessions, Stateless APIs und JWT Mental Model
Ziel
Heute verstehst du wichtige Themen zur REST-API-Sicherheitskonfiguration.
Die Kernfragen:
- Was ist CSRF?
- Wann sollte CSRF aktiviert bleiben?
- Wann wird CSRF üblicherweise deaktiviert?
- Was ist CORS?
- Was ist der Unterschied zwischen CORS und CSRF?
- Was ist session-basierte Sicherheit?
- Was ist zustandslose Sicherheit?
- Was ist JWT?
- Was ist ein Bearer Token?
- Wie funktioniert JWT-Authentifizierung?
- Was ist
SessionCreationPolicy.STATELESS? - Wie konfigurierst du Spring Security für REST APIs?
- Was sind typische Prüfungsfallen?
1. Kurz-Wiederholung aus Woche 6, Tag 3
An Tag 3 hast du gelernt:
- Autorisierung prüft Berechtigungen.
- Authentifizierung beweist Identität.
- Rollen sind Berechtigungen mit dem Präfix
ROLE_. hasRole("ADMIN")prüftROLE_ADMIN.hasAuthority("TASK_READ")prüft exaktTASK_READ.- URL-Autorisierung schützt Endpunkte.
- Method Security schützt Methoden.
@PreAuthorizeprüft vor der Methodenausführung.- Berechtigungen auf Datenebene gehören in Service-/Domain-Logik.
- Vertraue keiner vom Client gesendeten Benutzeridentität.
- Das Backend muss Autorisierung erzwingen.
Merksatz:
Authentication = who are you?
Authorization = what can you do?
Heute lernst du, wie sich die REST-API-Sicherheitskonfiguration je nach Browser-Sessions, zustandslosen APIs, CORS, CSRF und JWT ändert.
2. Gesamtbild
Spring Security kann verschiedene Anwendungsstile unterstützen.
Gängige Stile:
1. Traditional web app with server-side pages
2. Browser app with session cookie
3. REST API with HTTP Basic
4. REST API with JWT bearer token
5. OAuth2 / OpenID Connect login
6. OAuth2 Resource Server
Wichtig:
Security configuration depends on the application style.
Eine Konfiguration, die für eine zustandslose JWT-API korrekt ist, kann für eine Browser-Session-App falsch sein.
Merksatz:
Die Sicherheitskonfiguration hängt davon ab, wie der Client authentifiziert.
3. Session-basierte Sicherheit
Session-basierte Sicherheit bedeutet:
Der Server speichert den Login-Status in einer HTTP-Session.
Ablauf:
1. User logs in with username/password.
2. Server authenticates the user.
3. Server creates an HTTP session.
4. Browser receives a session cookie.
5. Browser sends the cookie on future requests.
6. Server uses the session to find the current user.
Das Session-Cookie heißt oft:
JSESSIONID
Merksatz:
Session-Sicherheit speichert den Authentifizierungsstatus auf dem Server.
4. Session-basierter Ablauf
Beispiel:
POST /login
Content-Type: application/x-www-form-urlencoded
username=user@example.com&password=password
Bei erfolgreichem Login antwortet der Server:
Set-Cookie: JSESSIONID=abc123; HttpOnly; Secure
Späterer Request:
GET /api/tasks
Cookie: JSESSIONID=abc123
Der Server nutzt die Session-ID, um die Authentifizierung zu finden.
Merksatz:
Bei Session-Sicherheit verweist das Cookie auf serverseitigen Login-Status.
5. Zustandslose Sicherheit
Zustandslose Sicherheit bedeutet:
Der Server speichert den Authentifizierungsstatus nicht in einer HTTP-Session.
Stattdessen sendet der Client bei jeder Anfrage Credentials oder ein Token.
Beispiel mit Bearer Token:
GET /api/tasks
Authorization: Bearer eyJhbGciOi...
Ablauf:
1. Client sends token.
2. Server validates token.
3. Server creates Authentication for this request.
4. Request is authorized.
5. Server does not need an HTTP session for login state.
Merksatz:
Zustandslose APIs authentifizieren jede Anfrage unabhängig.
6. Session vs. zustandslos
| Thema | Session-basiert | Zustandsloses Token |
|---|---|---|
| Login-Status | auf dem Server gespeichert | im Token gespeichert/repräsentiert |
| Client sendet | Session-Cookie | Bearer Token |
| Typisch für | Browser-Apps | REST APIs, Mobile Apps |
| Server-Speicher | Session-Speicher | meist keine Session |
| CSRF-Risiko | wichtig bei Cookies | meist geringer mit Authorization-Header |
| Skalierung | braucht Session-Strategie | einfacher zu skalieren |
Merksatz:
Session = server remembers.
Stateless = token proves each request.
7. Was ist CSRF?
CSRF bedeutet:
Cross-Site Request Forgery
Kurze Definition:
CSRF ist ein Angriff, bei dem eine bösartige Seite den Browser des Benutzers dazu bringt, eine authentifizierte Anfrage an eine andere Seite zu senden.
Beispiel:
User is logged in to bank.com.
Browser has bank.com session cookie.
User visits evil.com.
evil.com causes browser to send POST request to bank.com.
Browser automatically includes bank.com cookies.
Der gefährliche Teil:
Browser automatically sends cookies.
Merksatz:
CSRF missbraucht automatisch gesendete Browser-Cookies.
8. CSRF-Beispiel
Der Benutzer ist eingeloggt bei:
https://example-bank.com
Sein Browser hat:
JSESSIONID=abc123
Eine bösartige Website enthält:
<form action="https://example-bank.com/transfer" method="post">
<input name="amount" value="1000" />
<input name="to" value="attacker" />
</form>
<script>
document.forms[0].submit();
</script>
Wenn der Browser das Bank-Session-Cookie automatisch mitsendet, könnte die Bank die Anfrage für legitim halten.
CSRF-Schutz verhindert das, indem ein gültiges CSRF-Token verlangt wird.
Merksatz:
CSRF-Schutz beweist, dass die Anfrage von der echten Anwendungsseite kommt, nicht von einer anderen Seite.
9. Sichere und unsichere HTTP-Methoden
Sichere Methoden sollten den Server-Status nicht ändern.
Meist sicher:
GET
HEAD
OPTIONS
TRACE
Unsichere Methoden können den Server-Status ändern:
POST
PUT
PATCH
DELETE
CSRF-Schutz ist vor allem bei unsicheren Methoden wichtig.
Merksatz:
CSRF-Schutz ist am wichtigsten bei zustandsändernden Requests.
10. CSRF in Spring Security
Spring Security aktiviert CSRF-Schutz standardmäßig in vielen Servlet-Webanwendungen.
Das bedeutet: Unsichere Requests können ein CSRF-Token verlangen.
Beispiel für einen Testfehler:
POST /api/tasks returns 403
Möglicher Grund:
CSRF token is missing
Merksatz:
Mit aktiviertem CSRF brauchen unsichere Methoden ein gültiges CSRF-Token.
11. Wann CSRF aktiviert bleiben sollte
CSRF ist wichtig, wenn:
browser-based app
session cookie authentication
form login
server-rendered pages
cookies are automatically sent by browser
Beispiele:
Thymeleaf app with login session
React app using cookie-based session
traditional Spring MVC web app
Merksatz:
Wenn die Authentifizierung Browser-Cookies nutzt, nimm CSRF ernst.
12. Wann CSRF üblicherweise deaktiviert wird
CSRF wird bei zustandslosen REST APIs oft deaktiviert, wenn:
API uses Authorization: Bearer token
API does not rely on cookies for authentication
server does not use HTTP session for authentication
client sends token manually in header
Beispiel:
Authorization: Bearer eyJhbGciOi...
Grund:
Browser does not automatically attach custom Authorization bearer tokens to cross-site requests in the same way it automatically sends cookies.
Wichtig:
Do not disable CSRF blindly.
Understand the authentication mechanism first.
Merksatz:
CSRF ist vor allem ein Cookie-/Session-Problem, meist kein Bearer-Token-Header-Problem.
13. CSRF-Konfiguration
Für eine zustandslose REST API:
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
)
.build();
}
Bei einer Browser-Session-App deaktivierst du CSRF aber nicht blind.
Merksatz:
Deaktiviere CSRF nur, wenn der Anwendungsstil das sinnvoll macht.
14. Testen mit CSRF
Wenn CSRF aktiviert ist, braucht ein POST-Test ein CSRF-Token.
Beispiel:
mockMvc.perform(post("/api/tasks")
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content("""
{"title":"Learn Security"}
"""))
.andExpect(status().isCreated());
Ohne .with(csrf()) kann der Test liefern:
403 Forbidden
Merksatz:
In Tests können POST/PUT/PATCH/DELETE
.with(csrf())brauchen, wenn CSRF aktiviert ist.
15. Was ist CORS?
CORS bedeutet:
Cross-Origin Resource Sharing
CORS beantwortet:
Which browser origins are allowed to call my API?
Beispiel:
Frontend:
https://app.example.com
Backend API:
https://api.example.com
Verschiedene Origins.
Der Browser fragt:
Is https://app.example.com allowed to call https://api.example.com?
Merksatz:
CORS steuert, welche Browser-Origins die API aufrufen dürfen.
16. Was ist eine Origin?
Eine Origin ist:
scheme + host + port
Beispiele:
http://localhost:3000
http://localhost:8080
https://app.example.com
https://api.example.com
Das sind verschiedene Origins:
http://localhost:3000
http://localhost:8080
weil der Port unterschiedlich ist.
Merksatz:
Origin bedeutet Protokoll, Host und Port.
17. CORS-Beispiel
Frontend-Request:
GET https://api.example.com/api/tasks
Origin: https://app.example.com
Wenn die API es erlaubt, enthält die Antwort:
Access-Control-Allow-Origin: https://app.example.com
Dann erlaubt der Browser dem Frontend-JavaScript, die Antwort zu lesen.
Wenn nicht erlaubt, blockiert der Browser die Antwort.
Merksatz:
CORS wird vom Browser erzwungen.
18. Preflight-Request
Bei manchen Cross-Origin-Requests sendet der Browser zuerst einen Preflight-Request.
Beispiel:
OPTIONS /api/tasks
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Authorization, Content-Type
Der Server muss mit erlaubten Methoden/Headers antworten.
Wenn der Preflight fehlschlägt:
real request is not sent
Merksatz:
Preflight ist die Erlaubnisfrage des Browsers vor dem eigentlichen Request.
19. Warum CORS mit Spring Security funktionieren muss
CORS-Preflight-Requests enthalten meist keine Cookies oder Authentifizierung.
Wenn Spring Security Authentifizierung verlangt, bevor CORS verarbeitet wird, kann der Preflight abgelehnt werden.
Das verursacht Browser-Fehler.
Merksatz:
CORS muss so konfiguriert sein, dass Preflight-Requests korrekt erlaubt werden.
20. CORS vs. CSRF
CORS und CSRF sind unterschiedlich.
| Thema | CORS | CSRF |
|---|---|---|
| Hauptfrage | Welche Origins dürfen API aufrufen? | Ist dieser zustandsändernde Request gefälscht? |
| Erzwungen durch | Browser | serverseitiger Schutz |
| Typisches Symptom | Browser blockiert Antwort | Server liefert 403 |
| Bezug zu | Cross-Origin-JavaScript | automatische Cookies |
| Beispiel | React-App ruft API auf | bösartige Seite sendet Formular |
Merksatz:
CORS controls who can call from browser.
CSRF protects against forged browser requests.
21. Typische CORS-Konfiguration
Konfigurations-Bean:
@Configuration
public class CorsConfig {
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("https://app.example.com"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
config.setAllowedHeaders(List.of("Authorization", "Content-Type"));
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source =
new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}
Security-Konfiguration:
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.cors(Customizer.withDefaults())
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
)
.build();
}
Merksatz:
Definiere die CORS-Konfiguration und aktiviere
cors()in Spring Security.
22. CORS-Entwicklungsbeispiel
Lokales Frontend:
http://localhost:3000
Lokales Backend:
http://localhost:8080
CORS-Konfiguration:
config.setAllowedOrigins(List.of("http://localhost:3000"));
Nutze in Produktion keine breiten Wildcard-Einstellungen ohne Nachdenken.
Schlechte Produktionsgewohnheit:
config.setAllowedOrigins(List.of("*"));
Besonders gefährlich mit Credentials.
Merksatz:
Erlaube nur vertrauenswürdige Frontend-Origins.
23. allowCredentials
allowCredentials(true) erlaubt dem Browser, Credentials wie Cookies mitzusenden.
Bei Cookies/Session:
config.setAllowCredentials(true);
Dann kannst du keine Wildcard-Origin sicher nutzen:
*
Nutze explizite Origins.
Merksatz:
Credentials plus Wildcard-Origins sind eine gefährliche Kombination.
24. Zustandslose REST-API-Sicherheit
Eine zustandslose REST API nutzt üblicherweise:
Authorization: Bearer <token>
Die Konfiguration enthält meist:
CSRF disabled
session creation policy stateless
JWT/resource server or custom token filter
public auth endpoints
protected API endpoints
CORS configured for frontend
Merksatz:
Zustandslose REST APIs nutzen meist Bearer Tokens und keine serverseitige Login-Session.
25. SessionCreationPolicy
Die Session-Policy von Spring Security steuert die Session-Nutzung.
Gängige Werte:
ALWAYS
IF_REQUIRED
NEVER
STATELESS
Am wichtigsten für REST APIs:
SessionCreationPolicy.STATELESS
Bedeutung:
Spring Security should not create or use HTTP session for security context.
Merksatz:
STATELESSbedeutet: keine HTTP-Session für Authentifizierungsstatus nutzen.
26. Zustandslose Konfiguration — Beispiel
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.cors(Customizer.withDefaults())
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/actuator/health").permitAll()
.anyRequest().authenticated()
)
.build();
}
Das definiert noch keine JWT-Validierung.
Es sagt nur:
no CSRF token requirement
no HTTP session for auth state
public auth and health endpoints
other endpoints require authentication
Merksatz:
Zustandslose Konfiguration braucht einen Authentifizierungsmechanismus, meist Bearer Token/JWT.
27. Was ist JWT?
JWT bedeutet:
JSON Web Token
Ein JWT ist ein kompaktes Token-Format, das Claims enthalten kann.
Beispiel-Claims:
{
"sub": "user@example.com",
"userId": 10,
"tenantId": 5,
"roles": ["USER"],
"iat": 1720000000,
"exp": 1720003600
}
JWT wird meist als Bearer Token gesendet:
Authorization: Bearer eyJhbGciOi...
Merksatz:
JWT ist ein Token-Format, das Claims trägt.
28. JWT-Struktur
Ein JWT hat meist drei Teile:
header.payload.signature
Beispielform:
xxxxx.yyyyy.zzzzz
Header:
algorithm and token type
Payload:
claims such as subject, roles, expiry
Signatur:
proves token was issued by trusted signer and was not modified
Merksatz:
JWT hat Header, Payload und Signatur.
29. JWT ist nicht automatisch verschlüsselt
Wichtig:
JWT payload is usually Base64URL-encoded, not encrypted.
Das bedeutet: Clients können die Claims oft lesen.
Packe keine Geheimnisse in den JWT-Payload.
Schlecht:
{
"password": "secret123"
}
Gut:
{
"sub": "user@example.com",
"roles": ["USER"],
"exp": 1720003600
}
Merksatz:
JWT ist signiert, nicht zwingend verschlüsselt.
30. Bearer Token
Ein Bearer Token bedeutet:
Wer das Token besitzt, darf es nutzen.
Header:
Authorization: Bearer <token>
Wichtig:
Protect bearer tokens carefully.
Use HTTPS.
Do not log tokens.
Do not store them carelessly.
Merksatz:
Bearer Token bedeutet: Besitz gewährt Zugriff.
31. JWT-Login-Ablauf
Ein typischer eigener JWT-Login-Ablauf:
1. User sends email/password to POST /api/auth/login.
2. Server authenticates credentials using AuthenticationManager.
3. Server creates signed JWT.
4. Server returns JWT to client.
5. Client stores token.
6. Client sends Authorization: Bearer <jwt> on future requests.
7. Server validates JWT on every request.
8. If valid, server creates Authentication for the request.
Merksatz:
Login erzeugt Token; spätere Requests präsentieren Token.
32. JWT-Request-Ablauf
Request:
GET /api/tasks
Authorization: Bearer eyJhbGciOi...
Ablauf:
1. Security filter reads Authorization header.
2. Token is extracted.
3. Token signature is verified.
4. Expiration is checked.
5. Claims are read.
6. Authorities are created from claims.
7. Authentication is stored in SecurityContext.
8. Authorization rules are checked.
9. Controller runs if allowed.
Merksatz:
JWT-Validierung macht aus einem Token eine
Authentication.
33. JWT und Logout
Mit Sessions:
logout can invalidate server session
Mit zustandslosem JWT:
server may not store token
logout is harder
Optionen:
short token expiration
refresh tokens
token blacklist/revocation list
change signing key
OAuth2 authorization server handles revocation
Merksatz:
Zustandsloses JWT macht Logout/Widerruf schwieriger als Sessions.
34. JWT-Ablaufzeit
JWT sollte eine Ablaufzeit haben.
Häufiger Claim:
exp
Warum?
If token is stolen, it should not work forever.
Gutes Design:
short-lived access token
optional refresh token
secure storage
rotation/revocation strategy
Merksatz:
JWTs sollten ablaufen.
35. Eigener JWT-Filter vs. Resource Server
Es gibt zwei gängige Ansätze.
Eigener JWT-Filter
Du schreibst deinen eigenen Filter:
read Authorization header
validate token
create Authentication
set SecurityContext
Gut zum Lernen, aber fehleranfällig.
OAuth2 Resource Server
Spring Security validiert Bearer-JWTs mit Resource-Server-Support.
Beispiel-Konfiguration:
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(Customizer.withDefaults())
)
.build();
}
Merksatz:
Bevorzuge eingebauten Resource-Server-Support, wenn möglich.
36. Resource-Server-Dependency
Für OAuth2 Resource Server JWT-Support ist diese Dependency üblich:
implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server")
Dann konfigurierst du Issuer oder JWK-Set-URI.
Beispiel:
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://issuer.example.com
oder:
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: https://issuer.example.com/.well-known/jwks.json
Merksatz:
Der Resource Server validiert JWTs eines vertrauenswürdigen Authorization Servers.
37. JWT-Berechtigungs-Mapping
JWT kann Rollen/Scopes enthalten.
Beispiel-Payload:
{
"sub": "user@example.com",
"scope": "task:read task:write"
}
Spring Security kann Scopes auf Berechtigungen mappen.
Typische Berechtigungsform:
SCOPE_task:read
SCOPE_task:write
Dann die Regel:
.requestMatchers(HttpMethod.GET, "/api/tasks/**")
.hasAuthority("SCOPE_task:read")
Merksatz:
JWT-Claims müssen auf Spring-Security-Berechtigungen gemappt werden.
38. Eigene Claims — Beispiel
JWT-Payload:
{
"sub": "user@example.com",
"tenantId": 5,
"roles": ["ADMIN"]
}
Spring Security muss das in Berechtigungen wie:
ROLE_ADMIN
umwandeln — und ggf. eigenen Principal/Claims-Zugriff bereitstellen.
Wichtig:
JWT claims do not automatically become your exact roles unless configured.
Merksatz:
Token-Claims sind erst nützlich, wenn Spring sie auf
Authenticationund Berechtigungen mappt.
39. Wo JWT auf dem Client speichern?
Gängige Optionen:
memory
secure HTTP-only cookie
browser storage
mobile secure storage
Jede Option hat Trade-offs.
Wichtig:
LocalStorage is vulnerable if XSS happens.
Cookies can bring CSRF concerns if used for authentication.
Authorization header avoids automatic cookie sending.
Merksatz:
Die Token-Speicherwahl beeinflusst Sicherheitsrisiken.
40. REST-API-Security-Konfiguration — Beispiel
Beispiel für zustandslosen JWT Resource Server:
@Configuration
@EnableMethodSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.cors(Customizer.withDefaults())
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/actuator/health").permitAll()
.requestMatchers(HttpMethod.GET, "/api/tasks/**")
.hasAuthority("SCOPE_task:read")
.requestMatchers(HttpMethod.POST, "/api/tasks/**")
.hasAuthority("SCOPE_task:write")
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(Customizer.withDefaults())
)
.build();
}
}
Diese Konfiguration bedeutet:
CORS enabled
CSRF disabled for stateless API
no HTTP session for auth state
auth and health are public
task read/write require authorities
JWT bearer token authentication enabled
method security enabled
41. REST API mit eigenem Login + JWT
Ein eigener Login-Endpunkt kann öffentlich sein:
.requestMatchers("/api/auth/login").permitAll()
Login-Controller:
@PostMapping("/api/auth/login")
public TokenResponse login(@Valid @RequestBody LoginRequest request) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
request.email(),
request.password()
)
);
String token = jwtService.createToken(authentication);
return new TokenResponse(token);
}
Spätere Requests:
Authorization: Bearer <token>
Wichtig:
Login authenticates credentials.
JWT authenticates future requests.
Merksatz:
Eigener Login nutzt
AuthenticationManager; geschützte Endpunkte nutzen Bearer Token.
42. Typische REST-API-Endpunkt-Regeln
Typische öffentliche Endpunkte:
POST /api/auth/login
POST /api/auth/register
GET /actuator/health
GET /api/public/**
Typische geschützte Endpunkte:
/api/tasks/**
/api/clients/**
/api/users/me
/api/documents/**
Admin-Endpunkte:
/api/admin/**
Beispiel:
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/actuator/health").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
Merksatz:
Halte öffentliche Endpunkte explizit und schütze alles andere.
43. Default-Deny-Mindset
Eine sichere Denkweise:
Open only what must be public.
Require authentication for everything else.
Add stronger rules for admin or sensitive endpoints.
Gut:
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
Riskant:
.anyRequest().permitAll()
Merksatz:
Öffentlich als Ausnahme, geschützt als Standard.
44. Häufige REST-API-Fehler
Fehler 1:
Disabling CSRF without understanding authentication style.
Fehler 2:
Not configuring CORS for frontend origin.
Fehler 3:
Using sessions accidentally in a JWT API.
Fehler 4:
Returning tokens in logs.
Fehler 5:
Putting secrets in JWT claims.
Fehler 6:
Trusting JWT claims without verifying signature.
Fehler 7:
No token expiration.
Fehler 8:
Using wildcard CORS origins in production.
Fehler 9:
Using frontend authorization only.
Fehler 10:
Not mapping JWT claims to authorities correctly.
45. Security Headers — Kurznotiz
Spring Security hilft auch bei HTTP-Security-Headern.
Beispiele:
X-Content-Type-Options
Cache-Control
X-Frame-Options
Strict-Transport-Security
Content-Security-Policy
Deaktiviere Header nicht blind.
Merksatz:
Sicherheit ist mehr als Login; Header schützen auch den Browser.
46. HTTPS ist Pflicht
Für echte Anwendungen:
Use HTTPS.
Warum?
protects passwords
protects tokens
protects cookies
prevents many network attacks
Ohne HTTPS können Bearer Tokens und Basic-Credentials gestohlen werden.
Merksatz:
Ohne HTTPS gibt es keine echte Transportsicherheit.
47. Typische Prüfungsfallen
Falle 1
CSRF und CORS sind unterschiedlich.
Falle 2
CSRF schützt vor gefälschten, zustandsändernden Browser-Requests.
Falle 3
CORS steuert, welche Browser-Origins die API aufrufen dürfen.
Falle 4
CSRF ist besonders wichtig bei Browser-Cookies und Sessions.
Falle 5
Zustandslose Bearer-Token-APIs deaktivieren CSRF oft, aber nicht blind.
Falle 6
CORS-Preflight nutzt OPTIONS und hat oft keine Auth-Cookies.
Falle 7
Session-Sicherheit speichert Authentifizierungsstatus auf dem Server.
Falle 8
Zustandslose Sicherheit authentifiziert jede Anfrage unabhängig.
Falle 9
SessionCreationPolicy.STATELESS bedeutet keine HTTP-Session für den Security Context.
Falle 10
JWT ist signiert, nicht zwingend verschlüsselt.
Falle 11
Packe keine Geheimnisse in den JWT-Payload.
Falle 12
Bearer Token bedeutet: Wer das Token hat, darf es nutzen.
Falle 13
JWT sollte ablaufen.
Falle 14
JWT-Claims müssen auf Berechtigungen gemappt werden.
Falle 15
Nutze HTTPS für Credentials, Cookies und Tokens.
48. Echte Prüfungsfrage: CSRF
Frage:
Was ist CSRF?
Antwort:
CSRF ist ein Angriff, bei dem eine bösartige Seite den Browser eines Benutzers dazu bringt, eine authentifizierte, zustandsändernde Anfrage an eine andere Seite zu senden — oft über automatisch gesendete Cookies.
49. Echte Prüfungsfrage: CORS
Frage:
Was ist CORS?
Antwort:
CORS ist ein Browser-Sicherheitsmechanismus, der steuert, welche Origins Cross-Origin-Requests an einen Server stellen dürfen.
50. Echte Prüfungsfrage: CORS vs. CSRF
Frage:
Was ist der Unterschied zwischen CORS und CSRF?
Antwort:
CORS steuert, welche Browser-Origins eine API aufrufen dürfen. CSRF schützt vor gefälschten authentifizierten Browser-Requests, besonders wenn Cookies automatisch gesendet werden.
51. Echte Prüfungsfrage: Session-Sicherheit
Frage:
Was ist session-basierte Sicherheit?
Antwort:
Session-basierte Sicherheit speichert den Authentifizierungsstatus auf dem Server in einer HTTP-Session und nutzt ein Session-Cookie, um den Benutzer bei späteren Requests zu identifizieren.
52. Echte Prüfungsfrage: Zustandslose Sicherheit
Frage:
Was ist zustandslose Sicherheit?
Antwort:
Zustandslose Sicherheit bedeutet, dass der Server den Authentifizierungsstatus nicht in einer HTTP-Session speichert. Der Client sendet bei jeder Anfrage Credentials oder ein Token.
53. Echte Prüfungsfrage: JWT
Frage:
Was ist JWT?
Antwort:
JWT bedeutet JSON Web Token. Es ist ein kompaktes Token-Format, das Claims tragen kann und meist signiert ist, damit der Server prüfen kann, ob es nicht verändert wurde.
54. Echte Prüfungsfrage: Bearer Token
Frage:
Was ist ein Bearer Token?
Antwort:
Ein Bearer Token ist ein Token, bei dem Besitz Zugriff gewährt. Der Client sendet es üblicherweise im Header Authorization: Bearer <token>.
55. Echte Prüfungsfrage: Zustandslose Session-Policy
Frage:
Was bedeutet SessionCreationPolicy.STATELESS?
Antwort:
Es sagt Spring Security, keine HTTP-Session zum Speichern des Security Context zu erstellen oder zu nutzen.
56. Echte Prüfungsfrage: JWT-Verschlüsselung
Frage:
Ist der JWT-Payload immer verschlüsselt?
Antwort:
Nein. Ein JWT-Payload ist oft nur kodiert und signiert, nicht verschlüsselt. Packe keine Geheimnisse in JWT-Claims.
57. Interview-Antwort
Frage:
Erkläre CSRF und wann du es deaktivieren würdest.
Gute Antwort:
CSRF ist ein Angriff, bei dem eine bösartige Website den Browser dazu bringt, eine authentifizierte, zustandsändernde Anfrage an eine andere Seite zu senden — meist über Cookies, die der Browser automatisch mitsendet. Ich behalte CSRF-Schutz für Browser-Apps mit Sessions oder Cookies. Bei zustandslosen REST APIs mit Bearer Tokens im Authorization-Header, die nicht auf Cookies zur Authentifizierung angewiesen sind, wird CSRF oft deaktiviert — aber ich deaktiviere es nicht blind.
58. Interview-Antwort
Frage:
Erkläre CORS.
Gute Antwort:
CORS steuert, welche Browser-Origins eine API aufrufen dürfen. Es wird vom Browser erzwungen. Wenn eine React-App auf http://localhost:3000 eine Spring-Boot-API auf http://localhost:8080 aufruft, muss das Backend diese Origin erlauben. Bei nicht-einfachen Requests sendet der Browser zuerst einen Preflight-OPTIONS-Request, und der Server muss die angeforderte Methode und Header erlauben.
59. Interview-Antwort
Frage:
Was ist der Unterschied zwischen session-basierter und zustandsloser Authentifizierung?
Gute Antwort:
Bei session-basierter Authentifizierung speichert der Server den Authentifizierungsstatus in einer HTTP-Session, und der Browser sendet ein Session-Cookie. Bei zustandsloser Authentifizierung speichert der Server keinen Login-Status in einer Session. Der Client sendet bei jeder Anfrage ein Token — zum Beispiel ein JWT Bearer Token — und der Server validiert es jedes Mal.
60. Interview-Antwort
Frage:
Erkläre den JWT-Authentifizierungsablauf.
Gute Antwort:
Ein Benutzer loggt sich zuerst mit Benutzername und Passwort ein. Der Server authentifiziert die Credentials, meist mit AuthenticationManager. Bei Erfolg erstellt der Server ein signiertes JWT und gibt es an den Client zurück. Bei späteren Requests sendet der Client Authorization: Bearer <token>. Spring Security validiert das Token, liest Claims, erstellt eine Authentication, speichert sie im SecurityContext und wendet dann Autorisierungsregeln an.
61. Interview-Antwort
Frage:
Was sind häufige Fehler bei JWT-APIs?
Gute Antwort:
Häufige Fehler sind: kein HTTPS, sensible Daten in JWT-Claims, Tokens ohne Ablaufzeit, Tokens in Logs, fehlende Signatur-Validierung, falsches Mapping von Claims auf Berechtigungen, versehentliche Session-Nutzung und unsichere CORS-Einstellungen wie jede Origin in Produktion zu erlauben.
62. Kleine Code-Übung
Security-Konfiguration:
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.cors(Customizer.withDefaults())
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/actuator/health").permitAll()
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(Customizer.withDefaults())
)
.build();
}
Fragen:
- Ist CSRF aktiviert oder deaktiviert?
- Nutzt das eine HTTP-Session für Auth-Status?
- Welche Endpunkte sind öffentlich?
- Welcher Authentifizierungsstil gilt für geschützte Endpunkte?
- Was bedeutet
anyRequest().authenticated()?
Antworten:
- Deaktiviert.
- Nein, es nutzt
STATELESS. /api/auth/**und/actuator/health.- JWT Bearer Token Resource Server.
- Jeder andere Request erfordert Authentifizierung.
63. Kleine Bug-Übung 1
Problem:
.csrf(csrf -> csrf.disable())
Frage:
Ist das immer korrekt?
Antwort:
Nein. Es ist üblich bei zustandslosen Bearer-Token-REST-APIs, kann aber falsch sein bei Browser-Apps mit Session-Cookies. CSRF sollte nicht blind deaktiviert werden.
64. Kleine Bug-Übung 2
Problem:
Frontend:
http://localhost:3000
Backend:
http://localhost:8080
Browser-Fehler:
CORS policy blocked the request
Frage:
Was fehlt wahrscheinlich?
Antwort:
Das Backend erlaubt die Frontend-Origin wahrscheinlich nicht. Konfiguriere CORS für http://localhost:3000 und aktiviere CORS in Spring Security.
65. Kleine Bug-Übung 3
Problem:
JWT-Payload:
{
"sub": "user@example.com",
"password": "secret123"
}
Frage:
Was ist falsch?
Antwort:
Der JWT-Payload ist nicht zwingend verschlüsselt und kann oft vom Client gelesen werden. Packe niemals Passwörter oder Geheimnisse in JWT-Claims.
66. Kleine Bug-Übung 4
Problem:
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().permitAll()
Frage:
Was ist riskant?
Antwort:
Alles, was nicht /api/admin/** matched, ist öffentlich. Bei APIs ist es meist sicherer, nur bestimmte Endpunkte öffentlich zu machen und für alles andere Authentifizierung zu verlangen.
Besser:
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
Übungsfragen und Antworten
Frage 1
Was ist CSRF?
Antwort:
CSRF ist ein Angriff, bei dem eine bösartige Seite den Browser eines Benutzers dazu bringt, eine authentifizierte, zustandsändernde Anfrage an eine andere Seite zu senden.
Frage 2
Warum ist CSRF besonders bei Cookies wichtig?
Antwort:
Weil Browser Cookies — einschließlich Session-Cookies — bei Requests an die Cookie-Site automatisch mitsenden.
Frage 3
Wann wird CSRF üblicherweise deaktiviert?
Antwort:
CSRF wird üblicherweise bei zustandslosen REST APIs deaktiviert, die Bearer Tokens im Authorization-Header nutzen und nicht auf Cookies zur Authentifizierung angewiesen sind.
Frage 4
Was ist CORS?
Antwort:
CORS ist ein Browser-Mechanismus, der steuert, welche Origins Cross-Origin-Requests an eine API stellen dürfen.
Frage 5
Was ist eine Origin?
Antwort:
Eine Origin ist die Kombination aus Schema, Host und Port.
Frage 6
Was ist ein CORS-Preflight-Request?
Antwort:
Ein Preflight-Request ist ein OPTIONS-Request, den der Browser vor dem eigentlichen Cross-Origin-Request sendet, um zu prüfen, ob Methode und Header erlaubt sind.
Frage 7
Was ist der Unterschied zwischen CORS und CSRF?
Antwort:
CORS steuert, welche Browser-Origins die API aufrufen dürfen. CSRF schützt vor gefälschten authentifizierten Browser-Requests.
Frage 8
Was ist session-basierte Sicherheit?
Antwort:
Session-basierte Sicherheit speichert den Authentifizierungsstatus auf dem Server und nutzt ein Session-Cookie.
Frage 9
Was ist zustandslose Sicherheit?
Antwort:
Zustandslose Sicherheit speichert den Authentifizierungsstatus nicht in einer HTTP-Session. Der Client sendet bei jeder Anfrage ein Token oder Credentials.
Frage 10
Was bedeutet SessionCreationPolicy.STATELESS?
Antwort:
Es bedeutet, dass Spring Security keine HTTP-Session zum Speichern des Authentifizierungsstatus erstellen oder nutzen soll.
Frage 11
Was ist JWT?
Antwort:
JWT bedeutet JSON Web Token. Es ist ein kompaktes Token-Format, das Claims tragen kann und meist signiert ist.
Frage 12
Was sind die drei Teile eines JWT?
Antwort:
Header, Payload und Signatur.
Frage 13
Ist JWT immer verschlüsselt?
Antwort:
Nein. JWT ist meist signiert, aber nicht zwingend verschlüsselt.
Frage 14
Was ist ein Bearer Token?
Antwort:
Ein Bearer Token ist ein Token, bei dem wer es besitzt, damit auf geschützte Ressourcen zugreifen kann.
Frage 15
Warum sollten JWTs ablaufen?
Antwort:
Weil bei Diebstahl eines Tokens die Ablaufzeit begrenzt, wie lange es genutzt werden kann.
Frage 16
Was macht OAuth2 Resource Server Support?
Antwort:
Er erlaubt Spring Security, Endpunkte durch Validierung von OAuth2 Bearer Tokens wie JWTs zu schützen.
Frage 17
Was ist der Unterschied zwischen Login-Request und späteren JWT-Requests?
Antwort:
Der Login-Request authentifiziert Benutzername/Passwort und erzeugt ein Token. Spätere Requests nutzen das Token im Authorization-Header.
Frage 18
Warum solltest du Tokens nicht loggen?
Antwort:
Weil Tokens Zugriff gewähren können. Wenn Logs leaken, können Angreifer das Token nutzen.
Frage 19
Warum ist HTTPS erforderlich?
Antwort:
HTTPS schützt Credentials, Cookies und Tokens während des Transports.
Frage 20
Was ist ein sicheres Default-Mindset für Endpunkt-Sicherheit?
Antwort:
Öffne nur, was öffentlich sein muss. Verlange Authentifizierung für alles andere. Füge strengere Regeln für Admin- oder sensible Endpunkte hinzu.
Merksätze zum Mitnehmen
- CSRF bedeutet Cross-Site Request Forgery.
- CSRF missbraucht automatisch gesendete Browser-Cookies.
- CSRF ist besonders wichtig bei Session-/Cookie-Authentifizierung.
- Zustandslose Bearer-Token-APIs deaktivieren CSRF oft, aber nicht blind.
- CORS bedeutet Cross-Origin Resource Sharing.
- Origin bedeutet Schema, Host und Port.
- CORS steuert, welche Browser-Origins die API aufrufen dürfen.
- Preflight ist eine OPTIONS-Erlaubnisprüfung.
- CORS und CSRF sind unterschiedlich.
- Session-Sicherheit speichert Authentifizierungsstatus auf dem Server.
- Zustandslose Sicherheit authentifiziert jede Anfrage unabhängig.
SessionCreationPolicy.STATELESSbedeutet keine HTTP-Session für Auth-Status.- JWT bedeutet JSON Web Token.
- JWT hat Header, Payload und Signatur.
- JWT ist signiert, nicht zwingend verschlüsselt.
- Packe keine Geheimnisse in JWT-Claims.
- Bearer Token bedeutet: Besitz gewährt Zugriff.
- JWTs sollten ablaufen.
- Login erzeugt Token; spätere Requests präsentieren Token.
- JWT-Validierung erzeugt
Authentication. - JWT-Claims müssen auf Berechtigungen gemappt werden.
- Nutze HTTPS für echte Anwendungen.
- Öffentlich als Ausnahme, geschützt als Standard.