Zum Hauptinhalt springen

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:

  1. Was ist CSRF?
  2. Wann sollte CSRF aktiviert bleiben?
  3. Wann wird CSRF üblicherweise deaktiviert?
  4. Was ist CORS?
  5. Was ist der Unterschied zwischen CORS und CSRF?
  6. Was ist session-basierte Sicherheit?
  7. Was ist zustandslose Sicherheit?
  8. Was ist JWT?
  9. Was ist ein Bearer Token?
  10. Wie funktioniert JWT-Authentifizierung?
  11. Was ist SessionCreationPolicy.STATELESS?
  12. Wie konfigurierst du Spring Security für REST APIs?
  13. 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üft ROLE_ADMIN.
  • hasAuthority("TASK_READ") prüft exakt TASK_READ.
  • URL-Autorisierung schützt Endpunkte.
  • Method Security schützt Methoden.
  • @PreAuthorize prü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

ThemaSession-basiertZustandsloses Token
Login-Statusauf dem Server gespeichertim Token gespeichert/repräsentiert
Client sendetSession-CookieBearer Token
Typisch fürBrowser-AppsREST APIs, Mobile Apps
Server-SpeicherSession-Speichermeist keine Session
CSRF-Risikowichtig bei Cookiesmeist geringer mit Authorization-Header
Skalierungbraucht Session-Strategieeinfacher 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.

ThemaCORSCSRF
HauptfrageWelche Origins dürfen API aufrufen?Ist dieser zustandsändernde Request gefälscht?
Erzwungen durchBrowserserverseitiger Schutz
Typisches SymptomBrowser blockiert AntwortServer liefert 403
Bezug zuCross-Origin-JavaScriptautomatische Cookies
BeispielReact-App ruft API aufbö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:

STATELESS bedeutet: 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 Authentication und 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:

  1. Ist CSRF aktiviert oder deaktiviert?
  2. Nutzt das eine HTTP-Session für Auth-Status?
  3. Welche Endpunkte sind öffentlich?
  4. Welcher Authentifizierungsstil gilt für geschützte Endpunkte?
  5. Was bedeutet anyRequest().authenticated()?

Antworten:

  1. Deaktiviert.
  2. Nein, es nutzt STATELESS.
  3. /api/auth/** und /actuator/health.
  4. JWT Bearer Token Resource Server.
  5. 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.STATELESS bedeutet 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.