Careeroza
CSRF
What Is CSRF?
Cross-Site Request Forgery: you are logged into ShopEase in one tab. In another tab you open an evil page. That page silently submits a form to ShopEase. The browser automatically attaches your session cookie, so ShopEase thinks you sent it.
<!-- on evil-site.com -->
<form action="https://shopease.in/account/email" method="POST">
<input type="hidden" name="email" value="[email protected]">
</form>
<script>document.forms[0].submit()</script>The Fix: A Secret Token
Example
Spring Security puts a random CSRF token in your session and in every form it renders. A state-changing request (POST, PUT, PATCH, DELETE) must send it back. The evil site cannot read it, so its forged request fails:
import java.util.*;
public class Main {
// session id -> csrf token (Spring stores it in the HttpSession)
static final Map<String, String> CSRF = new HashMap<>();
static String handle(String method, String sessionId, String sentToken) {
boolean safe = method.equals("GET") || method.equals("HEAD") || method.equals("OPTIONS");
if (safe) return method + " -> 200 (no token needed)";
String expected = CSRF.get(sessionId);
if (expected == null || !expected.equals(sentToken)) return method + " -> 403 Invalid CSRF token";
return method + " -> 200 email changed";
}
public static void main(String[] args) {
CSRF.put("S1001", "a8f3-77c2-91de"); // generated at login, embedded in the real form
System.out.println("Real ShopEase form: " + handle("POST", "S1001", "a8f3-77c2-91de"));
System.out.println("Evil site (no token): " + handle("POST", "S1001", null));
System.out.println("Evil site (guess): " + handle("POST", "S1001", "0000-0000-0000"));
System.out.println("Page view: " + handle("GET", "S1001", null));
}
}Output
Real ShopEase form: POST -> 200 email changed Evil site (no token): POST -> 403 Invalid CSRF token Evil site (guess): POST -> 403 Invalid CSRF token Page view: GET -> 200 (no token needed)
CSRF in Spring Security
- CSRF protection is on by default for POST, PUT, PATCH and DELETE.
- Thymeleaf forms get the hidden
_csrffield automatically; the generated login and logout pages include it too. - A POST with curl and no token returns
403 Forbidden, a very common beginner surprise. - It is safe to disable CSRF only for APIs that do not use cookies for authentication (HTTP Basic or Bearer tokens sent by code).
// Stateless API chain: no session cookie, so CSRF cannot happen
http.csrf(csrf -> csrf.disable());
// Or keep it for the web pages and ignore only the API paths
http.csrf(csrf -> csrf.ignoringRequestMatchers("/api/**"));Note: SPA + cookie setups (React with a session cookie) need CookieCsrfTokenRepository; that is covered in the medium level, CORS and CSRF in Practice.