| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629 | 
							- [[servlet-csrf]]
 
- = Cross Site Request Forgery (CSRF)
 
- :figures: servlet/exploits
 
- In an application where end users can xref:servlet/authentication/index.adoc[log in], it is important to consider how to protect against xref:features/exploits/csrf.adoc#csrf[Cross Site Request Forgery (CSRF)].
 
- Spring Security protects against CSRF attacks by default for xref:features/exploits/csrf.adoc#csrf-protection-read-only[unsafe HTTP methods], such as a POST request, so no additional code is necessary.
 
- You can specify the default configuration explicitly using the following:
 
- [[csrf-configuration]]
 
- .Configure CSRF Protection
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		http
 
- 			// ...
 
- 			.csrf(Customizer.withDefaults());
 
- 		return http.build();
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
-     @Bean
 
-     open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
-         http {
 
-             // ...
 
-             csrf { }
 
-         }
 
-         return http.build()
 
-     }
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <http>
 
- 	<!-- ... -->
 
- 	<csrf/>
 
- </http>
 
- ----
 
- ======
 
- To learn more about CSRF protection for your application, consider the following use cases:
 
- * I want to <<csrf-components,understand CSRF protection's components>>
 
- * I need to <<migrating-to-spring-security-6,migrate an application from Spring Security 5 to 6>>
 
- * I want to <<csrf-token-repository-cookie,store the `CsrfToken` in a cookie>> instead of <<csrf-token-repository-httpsession,the session>>
 
- * I want to <<csrf-token-repository-custom,store the `CsrfToken` in a custom location>>
 
- * I want to <<deferred-csrf-token-opt-out,opt-out of deferred tokens>>
 
- * I want to <<csrf-token-request-handler-opt-out-of-breach,opt-out of BREACH protection>>
 
- * I need guidance integrating <<csrf-integration-form,Thymeleaf, JSPs or another view technology>> with the backend
 
- * I need guidance integrating <<csrf-integration-javascript,Angular or another JavaScript framework>> with the backend
 
- * I need guidance integrating <<csrf-integration-mobile,a mobile application or another client>> with the backend
 
- * I need guidance on <<csrf-access-denied-handler,handling errors>>
 
- * I want to <<csrf-testing,test CSRF protection>>
 
- * I need guidance on <<disable-csrf,disabling CSRF protection>>
 
- [[csrf-components]]
 
- == Understanding CSRF Protection's Components
 
- CSRF protection is provided by several components that are composed within the javadoc:org.springframework.security.web.csrf.CsrfFilter[]:
 
- .`CsrfFilter` Components
 
- [.invert-dark]
 
- image::{figures}/csrf.png[]
 
- CSRF protection is divided into two parts:
 
- 1. Make the javadoc:org.springframework.security.web.csrf.CsrfToken[] available to the application by delegating to the <<csrf-token-request-handler,`CsrfTokenRequestHandler`>>.
 
- 2. Determine if the request requires CSRF protection, load and validate the token, and <<csrf-access-denied-handler,handle `AccessDeniedException`>>.
 
- .`CsrfFilter` Processing
 
- [.invert-dark]
 
- image::{figures}/csrf-processing.png[]
 
- * image:{icondir}/number_1.png[] First, the javadoc:org.springframework.security.web.csrf.DeferredCsrfToken[] is loaded, which holds a reference to the <<csrf-token-repository,`CsrfTokenRepository`>> so that the persisted `CsrfToken` can be loaded later (in image:{icondir}/number_4.png[]).
 
- * image:{icondir}/number_2.png[] Second, a `Supplier<CsrfToken>` (created from `DeferredCsrfToken`) is given to the <<csrf-token-request-handler,`CsrfTokenRequestHandler`>>, which is responsible for populating a request attribute to make the `CsrfToken` available to the rest of the application.
 
- * image:{icondir}/number_3.png[] Next, the main CSRF protection processing begins and checks if the current request requires CSRF protection. If not required, the filter chain is continued and processing ends.
 
- * image:{icondir}/number_4.png[] If CSRF protection is required, the persisted `CsrfToken` is finally loaded from the `DeferredCsrfToken`.
 
- * image:{icondir}/number_5.png[] Continuing, the actual CSRF token provided by the client (if any) is resolved using the <<csrf-token-request-handler,`CsrfTokenRequestHandler`>>.
 
- * image:{icondir}/number_6.png[] The actual CSRF token is compared against the persisted `CsrfToken`. If valid, the filter chain is continued and processing ends.
 
- * image:{icondir}/number_7.png[] If the actual CSRF token is invalid (or missing), an `AccessDeniedException` is passed to the <<csrf-access-denied-handler,`AccessDeniedHandler`>> and processing ends.
 
- [[migrating-to-spring-security-6]]
 
- == Migrating to Spring Security 6
 
- When migrating from Spring Security 5 to 6, there are a few changes that may impact your application.
 
- The following is an overview of the aspects of CSRF protection that have changed in Spring Security 6:
 
- * Loading of the `CsrfToken` is now <<deferred-csrf-token,deferred by default>> to improve performance by no longer requiring the session to be loaded on every request.
 
- * The `CsrfToken` now includes <<csrf-token-request-handler-breach,randomness on every request by default>> to protect the CSRF token from a https://en.wikipedia.org/wiki/BREACH[BREACH] attack.
 
- [TIP]
 
- ====
 
- The changes in Spring Security 6 require additional configuration for single-page applications, and as such you may find the <<csrf-integration-javascript-spa>> section particularly useful.
 
- ====
 
- See the https://docs.spring.io/spring-security/reference/5.8/migration/servlet/exploits.html[Exploit Protection] section of the https://docs.spring.io/spring-security/reference/5.8/migration/index.html[Migration] chapter for more information on migrating a Spring Security 5 application.
 
- [[csrf-token-repository]]
 
- == Persisting the `CsrfToken`
 
- The `CsrfToken` is persisted using a `CsrfTokenRepository`.
 
- By default, the <<csrf-token-repository-httpsession,`HttpSessionCsrfTokenRepository`>> is used for storing tokens in a session.
 
- Spring Security also provides the <<csrf-token-repository-cookie,`CookieCsrfTokenRepository`>> for storing tokens in a cookie.
 
- You can also specify <<csrf-token-repository-custom,your own implementation>> to store tokens wherever you like.
 
- [[csrf-token-repository-httpsession]]
 
- === Using the `HttpSessionCsrfTokenRepository`
 
- By default, Spring Security stores the expected CSRF token in the `HttpSession` by using javadoc:org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository[], so no additional code is necessary.
 
- The `HttpSessionCsrfTokenRepository` reads the token from a session (whether in-memory, cache, or database). If you need to access the session attribute directly, please first configure the session attribute name using `HttpSessionCsrfTokenRepository#setSessionAttributeName`.
 
- You can specify the default configuration explicitly using the following configuration:
 
- [[csrf-token-repository-httpsession-configuration]]
 
- .Configure `HttpSessionCsrfTokenRepository`
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		http
 
- 			// ...
 
- 			.csrf((csrf) -> csrf
 
- 				.csrfTokenRepository(new HttpSessionCsrfTokenRepository())
 
- 			);
 
- 		return http.build();
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
-     @Bean
 
-     open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
-         http {
 
-             // ...
 
-             csrf {
 
-                 csrfTokenRepository = HttpSessionCsrfTokenRepository()
 
-             }
 
-         }
 
-         return http.build()
 
-     }
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <http>
 
- 	<!-- ... -->
 
- 	<csrf token-repository-ref="tokenRepository"/>
 
- </http>
 
- <b:bean id="tokenRepository"
 
- 	class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository"/>
 
- ----
 
- ======
 
- [[csrf-token-repository-cookie]]
 
- === Using the `CookieCsrfTokenRepository`
 
- You can persist the `CsrfToken` in a cookie to <<csrf-integration-javascript,support a JavaScript-based application>> using the javadoc:org.springframework.security.web.csrf.CookieCsrfTokenRepository[].
 
- The `CookieCsrfTokenRepository` writes to a cookie named `XSRF-TOKEN` and reads it from an HTTP request header named `X-XSRF-TOKEN` or the request parameter `_csrf` by default.
 
- These defaults come from Angular and its predecessor https://docs.angularjs.org/api/ng/service/$http#cross-site-request-forgery-xsrf-protection[AngularJS].
 
- [TIP]
 
- ====
 
- See the https://angular.io/guide/http-security-xsrf-protection[Cross-Site Request Forgery (XSRF) protection] guide and the https://angular.io/api/common/http/HttpClientXsrfModule[HttpClientXsrfModule] for more recent information on this topic.
 
- ====
 
- You can configure the `CookieCsrfTokenRepository` using the following configuration:
 
- [[csrf-token-repository-cookie-configuration]]
 
- .Configure `CookieCsrfTokenRepository`
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		http
 
- 			// ...
 
- 			.csrf((csrf) -> csrf
 
- 				.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
 
- 			);
 
- 		return http.build();
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
-     @Bean
 
-     open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
-         http {
 
-             // ...
 
-             csrf {
 
-                 csrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse()
 
-             }
 
-         }
 
-         return http.build()
 
-     }
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <http>
 
- 	<!-- ... -->
 
- 	<csrf token-repository-ref="tokenRepository"/>
 
- </http>
 
- <b:bean id="tokenRepository"
 
- 	class="org.springframework.security.web.csrf.CookieCsrfTokenRepository"
 
- 	p:cookieHttpOnly="false"/>
 
- ----
 
- ======
 
- [NOTE]
 
- ====
 
- The example explicitly sets `HttpOnly` to `false`.
 
- This is necessary to let JavaScript frameworks (such as Angular) read it.
 
- If you do not need the ability to read the cookie with JavaScript directly, we _recommend_ omitting `HttpOnly` (by using `new CookieCsrfTokenRepository()` instead) to improve security.
 
- ====
 
- [[csrf-token-repository-custom]]
 
- === Customizing the `CsrfTokenRepository`
 
- There can be cases where you want to implement a custom javadoc:org.springframework.security.web.csrf.CsrfTokenRepository[].
 
- Once you've implemented the `CsrfTokenRepository` interface, you can configure Spring Security to use it with the following configuration:
 
- [[csrf-token-repository-custom-configuration]]
 
- .Configure Custom `CsrfTokenRepository`
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		http
 
- 			// ...
 
- 			.csrf((csrf) -> csrf
 
- 				.csrfTokenRepository(new CustomCsrfTokenRepository())
 
- 			);
 
- 		return http.build();
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
-     @Bean
 
-     open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
-         http {
 
-             // ...
 
-             csrf {
 
-                 csrfTokenRepository = CustomCsrfTokenRepository()
 
-             }
 
-         }
 
-         return http.build()
 
-     }
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <http>
 
- 	<!-- ... -->
 
- 	<csrf token-repository-ref="tokenRepository"/>
 
- </http>
 
- <b:bean id="tokenRepository"
 
- 	class="example.CustomCsrfTokenRepository"/>
 
- ----
 
- ======
 
- [[csrf-token-request-handler]]
 
- == Handling the `CsrfToken`
 
- The `CsrfToken` is made available to an application using a `CsrfTokenRequestHandler`.
 
- This component is also responsible for resolving the `CsrfToken` from HTTP headers or request parameters.
 
- By default, the <<csrf-token-request-handler-breach,`XorCsrfTokenRequestAttributeHandler`>> is used for providing https://en.wikipedia.org/wiki/BREACH[BREACH] protection of the `CsrfToken`.
 
- Spring Security also provides the <<csrf-token-request-handler-plain,`CsrfTokenRequestAttributeHandler`>> for opting out of BREACH protection.
 
- You can also specify <<csrf-token-request-handler-custom,your own implementation>> to customize the strategy for handling and resolving tokens.
 
- [[csrf-token-request-handler-breach]]
 
- === Using the `XorCsrfTokenRequestAttributeHandler` (BREACH)
 
- The `XorCsrfTokenRequestAttributeHandler` makes the `CsrfToken` available as an `HttpServletRequest` attribute called `_csrf`, and additionally provides protection for https://en.wikipedia.org/wiki/BREACH[BREACH].
 
- [NOTE]
 
- ====
 
- The `CsrfToken` is also made available as a request attribute using the name `CsrfToken.class.getName()`.
 
- This name is not configurable, but the name `_csrf` can be changed using `XorCsrfTokenRequestAttributeHandler#setCsrfRequestAttributeName`.
 
- ====
 
- This implementation also resolves the token value from the request as either a request header (one of <<csrf-token-repository-httpsession,`X-CSRF-TOKEN`>> or <<csrf-token-repository-cookie,`X-XSRF-TOKEN`>> by default) or a request parameter (`_csrf` by default).
 
- [NOTE]
 
- ====
 
- BREACH protection is provided by encoding randomness into the CSRF token value to ensure the returned `CsrfToken` changes on every request.
 
- When the token is later resolved as a header value or request parameter, it is decoded to obtain the raw token which is then compared to the <<csrf-token-repository,persisted `CsrfToken`>>.
 
- ====
 
- Spring Security protects the CSRF token from a BREACH attack by default, so no additional code is necessary.
 
- You can specify the default configuration explicitly using the following configuration:
 
- [[csrf-token-request-handler-breach-configuration]]
 
- .Configure BREACH protection
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		http
 
- 			// ...
 
- 			.csrf((csrf) -> csrf
 
- 				.csrfTokenRequestHandler(new XorCsrfTokenRequestAttributeHandler())
 
- 			);
 
- 		return http.build();
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
-     @Bean
 
-     open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
-         http {
 
-             // ...
 
-             csrf {
 
-                 csrfTokenRequestHandler = XorCsrfTokenRequestAttributeHandler()
 
-             }
 
-         }
 
-         return http.build()
 
-     }
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <http>
 
- 	<!-- ... -->
 
- 	<csrf request-handler-ref="requestHandler"/>
 
- </http>
 
- <b:bean id="requestHandler"
 
- 	class="org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler"/>
 
- ----
 
- ======
 
- [[csrf-token-request-handler-plain]]
 
- === Using the `CsrfTokenRequestAttributeHandler`
 
- The `CsrfTokenRequestAttributeHandler` makes the `CsrfToken` available as an `HttpServletRequest` attribute called `_csrf`.
 
- [NOTE]
 
- ====
 
- The `CsrfToken` is also made available as a request attribute using the name `CsrfToken.class.getName()`.
 
- This name is not configurable, but the name `_csrf` can be changed using `CsrfTokenRequestAttributeHandler#setCsrfRequestAttributeName`.
 
- ====
 
- This implementation also resolves the token value from the request as either a request header (one of <<csrf-token-repository-httpsession,`X-CSRF-TOKEN`>> or <<csrf-token-repository-cookie,`X-XSRF-TOKEN`>> by default) or a request parameter (`_csrf` by default).
 
- [[csrf-token-request-handler-opt-out-of-breach]]
 
- The primary use of `CsrfTokenRequestAttributeHandler` is to opt-out of BREACH protection of the `CsrfToken`, which can be configured using the following configuration:
 
- .Opt-out of BREACH protection
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		http
 
- 			// ...
 
- 			.csrf((csrf) -> csrf
 
- 				.csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler())
 
- 			);
 
- 		return http.build();
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
-     @Bean
 
-     open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
-         http {
 
-             // ...
 
-             csrf {
 
-                 csrfTokenRequestHandler = CsrfTokenRequestAttributeHandler()
 
-             }
 
-         }
 
-         return http.build()
 
-     }
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <http>
 
- 	<!-- ... -->
 
- 	<csrf request-handler-ref="requestHandler"/>
 
- </http>
 
- <b:bean id="requestHandler"
 
- 	class="org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler"/>
 
- ----
 
- ======
 
- [[csrf-token-request-handler-custom]]
 
- === Customizing the `CsrfTokenRequestHandler`
 
- You can implement the `CsrfTokenRequestHandler` interface to customize the strategy for handling and resolving tokens.
 
- [TIP]
 
- ====
 
- The `CsrfTokenRequestHandler` interface is a `@FunctionalInterface` that can be implemented using a lambda expression to customize request handling.
 
- You will need to implement the full interface to customize how tokens are resolved from the request.
 
- See <<csrf-integration-javascript-spa-configuration>> for an example that uses delegation to implement a custom strategy for handling and resolving tokens.
 
- ====
 
- Once you've implemented the `CsrfTokenRequestHandler` interface, you can configure Spring Security to use it with the following configuration:
 
- [[csrf-token-request-handler-custom-configuration]]
 
- .Configure Custom `CsrfTokenRequestHandler`
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		http
 
- 			// ...
 
- 			.csrf((csrf) -> csrf
 
- 				.csrfTokenRequestHandler(new CustomCsrfTokenRequestHandler())
 
- 			);
 
- 		return http.build();
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
-     @Bean
 
-     open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
-         http {
 
-             // ...
 
-             csrf {
 
-                 csrfTokenRequestHandler = CustomCsrfTokenRequestHandler()
 
-             }
 
-         }
 
-         return http.build()
 
-     }
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <http>
 
- 	<!-- ... -->
 
- 	<csrf request-handler-ref="requestHandler"/>
 
- </http>
 
- <b:bean id="requestHandler"
 
- 	class="example.CustomCsrfTokenRequestHandler"/>
 
- ----
 
- ======
 
- [[deferred-csrf-token]]
 
- == Deferred Loading of the `CsrfToken`
 
- By default, Spring Security defers loading of the `CsrfToken` until it is needed.
 
- [NOTE]
 
- ====
 
- The `CsrfToken` is needed whenever a request is made with an xref:features/exploits/csrf.adoc#csrf-protection-read-only[unsafe HTTP method], such as a POST.
 
- Additionally, it is needed by any request that renders the token to the response, such as a web page with a `<form>` tag that includes a hidden `<input>` for the CSRF token.
 
- ====
 
- Because Spring Security also stores the `CsrfToken` in the `HttpSession` by default, deferred CSRF tokens can improve performance by not requiring the session to be loaded on every request.
 
- [[deferred-csrf-token-opt-out]]
 
- In the event that you want to opt-out of deferred tokens and cause the `CsrfToken` to be loaded on every request, you can do so with the following configuration:
 
- [[deferred-csrf-token-opt-out-configuration]]
 
- .Opt-out of Deferred CSRF Tokens
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		XorCsrfTokenRequestAttributeHandler requestHandler = new XorCsrfTokenRequestAttributeHandler();
 
- 		// set the name of the attribute the CsrfToken will be populated on
 
- 		requestHandler.setCsrfRequestAttributeName(null);
 
- 		http
 
- 			// ...
 
- 			.csrf((csrf) -> csrf
 
- 				.csrfTokenRequestHandler(requestHandler)
 
- 			);
 
- 		return http.build();
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
-     @Bean
 
-     open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
-         val requestHandler = XorCsrfTokenRequestAttributeHandler()
 
-         // set the name of the attribute the CsrfToken will be populated on
 
-         requestHandler.setCsrfRequestAttributeName(null)
 
-         http {
 
-             // ...
 
-             csrf {
 
-                 csrfTokenRequestHandler = requestHandler
 
-             }
 
-         }
 
-         return http.build()
 
-     }
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <http>
 
- 	<!-- ... -->
 
- 	<csrf request-handler-ref="requestHandler"/>
 
- </http>
 
- <b:bean id="requestHandler"
 
- 	class="org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler">
 
- 	<b:property name="csrfRequestAttributeName">
 
- 		<b:null/>
 
- 	</b:property>
 
- </b:bean>
 
- ----
 
- ======
 
- [NOTE]
 
- ====
 
- By setting the `csrfRequestAttributeName` to `null`, the `CsrfToken` must first be loaded to determine what attribute name to use.
 
- This causes the `CsrfToken` to be loaded on every request.
 
- ====
 
- [[csrf-integration]]
 
- == Integrating with CSRF Protection
 
- For the xref:features/exploits/csrf.adoc#csrf-protection-stp[synchronizer token pattern] to protect against CSRF attacks, we must include the actual CSRF token in the HTTP request.
 
- This must be included in a part of the request (a form parameter, an HTTP header, or other part) that is not automatically included in the HTTP request by the browser.
 
- The following sections describe the various ways a frontend or client application can integrate with a CSRF-protected backend application:
 
- * <<csrf-integration-form>>
 
- * <<csrf-integration-javascript>>
 
- * <<csrf-integration-mobile>>
 
- [[csrf-integration-form]]
 
- === HTML Forms
 
- To submit an HTML form, the CSRF token must be included in the form as a hidden input.
 
- For example, the rendered HTML might look like:
 
- .CSRF Token in HTML Form
 
- [source,html]
 
- ----
 
- <input type="hidden"
 
- 	name="_csrf"
 
- 	value="4bfd1575-3ad1-4d21-96c7-4ef2d9f86721"/>
 
- ----
 
- The following view technologies automatically include the actual CSRF token in a form that has an unsafe HTTP method, such as a POST:
 
- * https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-view-jsp-formtaglib[Spring’s form tag library]
 
- * https://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#integration-with-requestdatavalueprocessor[Thymeleaf]
 
- * Any other view technology that integrates with {spring-framework-api-url}org/springframework/web/servlet/support/RequestDataValueProcessor.html[`RequestDataValueProcessor`] (via javadoc:org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor[])
 
- * You can also include the token yourself via the xref:servlet/integrations/jsp-taglibs.adoc#taglibs-csrfinput[csrfInput] tag
 
- If these options are not available, you can take advantage of the fact that the `CsrfToken` is exposed as an <<csrf-token-request-handler,`HttpServletRequest` attribute named `_csrf`>>.
 
- The following example does this with a JSP:
 
- .CSRF Token in HTML Form with Request Attribute
 
- [source,xml]
 
- ----
 
- <c:url var="logoutUrl" value="/logout"/>
 
- <form action="${logoutUrl}"
 
- 	method="post">
 
- <input type="submit"
 
- 	value="Log out" />
 
- <input type="hidden"
 
- 	name="${_csrf.parameterName}"
 
- 	value="${_csrf.token}"/>
 
- </form>
 
- ----
 
- [[csrf-integration-javascript]]
 
- === JavaScript Applications
 
- JavaScript applications typically use JSON instead of HTML.
 
- If you use JSON, you can submit the CSRF token within an HTTP request header instead of a request parameter.
 
- In order to obtain the CSRF token, you can configure Spring Security to store the expected CSRF token <<csrf-token-repository-cookie,in a cookie>>.
 
- By storing the expected token in a cookie, JavaScript frameworks such as https://angular.io/api/common/http/HttpClientXsrfModule[Angular] can automatically include the actual CSRF token as an HTTP request header.
 
- [TIP]
 
- ====
 
- There are special considerations for BREACH protection and deferred tokens when integrating a single-page application (SPA) with Spring Security's CSRF protection.
 
- A full configuration example is provided in the <<csrf-integration-javascript-spa,next section>>.
 
- ====
 
- You can read about different types of JavaScript applications in the following sections:
 
- * <<csrf-integration-javascript-spa>>
 
- * <<csrf-integration-javascript-mpa>>
 
- * <<csrf-integration-javascript-other>>
 
- [[csrf-integration-javascript-spa]]
 
- ==== Single-Page Applications
 
- There are special considerations for integrating a single-page application (SPA) with Spring Security's CSRF protection.
 
- Recall that Spring Security provides <<csrf-token-request-handler-breach,BREACH protection of the `CsrfToken`>> by default.
 
- When storing the expected CSRF token <<csrf-token-repository-cookie,in a cookie>>, JavaScript applications will only have access to the plain token value and _will not_ have access to the encoded value.
 
- A <<csrf-token-request-handler-custom,customized request handler>> for resolving the actual token value will need to be provided.
 
- In addition, the cookie storing the CSRF token will be cleared upon authentication success and logout success.
 
- Spring Security defers loading a new CSRF token by default, and additional work is required to return a fresh cookie.
 
- [NOTE]
 
- ====
 
- Refreshing the token after authentication success and logout success is required because the javadoc:org.springframework.security.web.csrf.CsrfAuthenticationStrategy[] and javadoc:org.springframework.security.web.csrf.CsrfLogoutHandler[] will clear the previous token.
 
- The client application will not be able to perform an unsafe HTTP request, such as a POST, without obtaining a fresh token.
 
- ====
 
- In order to easily integrate a single-page application with Spring Security, the following configuration can be used:
 
- [[csrf-integration-javascript-spa-configuration]]
 
- .Configure CSRF for Single-Page Application
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		http
 
- 			// ...
 
- 			.csrf((csrf) -> csrf
 
- 				.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())   // <1>
 
- 				.csrfTokenRequestHandler(new SpaCsrfTokenRequestHandler())            // <2>
 
- 			);
 
- 		return http.build();
 
- 	}
 
- }
 
- final class SpaCsrfTokenRequestHandler implements CsrfTokenRequestHandler {
 
- 	private final CsrfTokenRequestHandler plain = new CsrfTokenRequestAttributeHandler();
 
- 	private final CsrfTokenRequestHandler xor = new XorCsrfTokenRequestAttributeHandler();
 
- 	@Override
 
- 	public void handle(HttpServletRequest request, HttpServletResponse response, Supplier<CsrfToken> csrfToken) {
 
- 		/*
 
- 		 * Always use XorCsrfTokenRequestAttributeHandler to provide BREACH protection of
 
- 		 * the CsrfToken when it is rendered in the response body.
 
- 		 */
 
- 		this.xor.handle(request, response, csrfToken);
 
- 		/*
 
- 		 * Render the token value to a cookie by causing the deferred token to be loaded.
 
- 		 */
 
- 		csrfToken.get();
 
- 	}
 
- 	@Override
 
- 	public String resolveCsrfTokenValue(HttpServletRequest request, CsrfToken csrfToken) {
 
- 		String headerValue = request.getHeader(csrfToken.getHeaderName());
 
- 		/*
 
- 		 * If the request contains a request header, use CsrfTokenRequestAttributeHandler
 
- 		 * to resolve the CsrfToken. This applies when a single-page application includes
 
- 		 * the header value automatically, which was obtained via a cookie containing the
 
- 		 * raw CsrfToken.
 
- 		 *
 
- 		 * In all other cases (e.g. if the request contains a request parameter), use
 
- 		 * XorCsrfTokenRequestAttributeHandler to resolve the CsrfToken. This applies
 
- 		 * when a server-side rendered form includes the _csrf request parameter as a
 
- 		 * hidden input.
 
- 		 */
 
- 		return (StringUtils.hasText(headerValue) ? this.plain : this.xor).resolveCsrfTokenValue(request, csrfToken);
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
-     @Bean
 
-     open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
-         http {
 
-             // ...
 
-             csrf {
 
-                 csrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse()   // <1>
 
-                 csrfTokenRequestHandler = SpaCsrfTokenRequestHandler()                // <2>
 
-             }
 
-         }
 
-         return http.build()
 
-     }
 
- }
 
- class SpaCsrfTokenRequestHandler : CsrfTokenRequestHandler {
 
-     private val plain: CsrfTokenRequestHandler = CsrfTokenRequestAttributeHandler()
 
-     private val xor: CsrfTokenRequestHandler = XorCsrfTokenRequestAttributeHandler()
 
-     override fun handle(request: HttpServletRequest, response: HttpServletResponse, csrfToken: Supplier<CsrfToken>) {
 
-         /*
 
-          * Always use XorCsrfTokenRequestAttributeHandler to provide BREACH protection of
 
-          * the CsrfToken when it is rendered in the response body.
 
-          */
 
-         xor.handle(request, response, csrfToken)
 
-         /*
 
-          * Render the token value to a cookie by causing the deferred token to be loaded.
 
-          */
 
-         csrfToken.get()
 
-     }
 
-     override fun resolveCsrfTokenValue(request: HttpServletRequest, csrfToken: CsrfToken): String? {
 
-         val headerValue = request.getHeader(csrfToken.headerName)
 
-         /*
 
-          * If the request contains a request header, use CsrfTokenRequestAttributeHandler
 
-          * to resolve the CsrfToken. This applies when a single-page application includes
 
-          * the header value automatically, which was obtained via a cookie containing the
 
-          * raw CsrfToken.
 
-          */
 
-         return if (StringUtils.hasText(headerValue)) {
 
-             plain
 
-         } else {
 
-             /*
 
-              * In all other cases (e.g. if the request contains a request parameter), use
 
-              * XorCsrfTokenRequestAttributeHandler to resolve the CsrfToken. This applies
 
-              * when a server-side rendered form includes the _csrf request parameter as a
 
-              * hidden input.
 
-              */
 
-             xor
 
-         }.resolveCsrfTokenValue(request, csrfToken)
 
-     }
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <http>
 
- 	<!-- ... -->
 
- 	<csrf
 
- 		token-repository-ref="tokenRepository"                                        <1>
 
- 		request-handler-ref="requestHandler"/>                                        <2>
 
- </http>
 
- <b:bean id="tokenRepository"
 
- 	class="org.springframework.security.web.csrf.CookieCsrfTokenRepository"
 
- 	p:cookieHttpOnly="false"/>
 
- <b:bean id="requestHandler"
 
- 	class="example.SpaCsrfTokenRequestHandler"/>
 
- ----
 
- ======
 
- <1> Configure `CookieCsrfTokenRepository` with `HttpOnly` set to `false` so the cookie can be read by the JavaScript application.
 
- <2> Configure a custom `CsrfTokenRequestHandler` that resolves the CSRF token based on whether it is an HTTP request header (`X-XSRF-TOKEN`) or request parameter (`_csrf`).
 
-     This implementation also causes the deferred `CsrfToken` to be loaded on every request, which will return a new cookie if needed.
 
- [[csrf-integration-javascript-mpa]]
 
- ==== Multi-Page Applications
 
- For multi-page applications where JavaScript is loaded on each page, an alternative to exposing the CSRF token <<csrf-token-repository-cookie,in a cookie>> is to include the CSRF token within your `meta` tags.
 
- The HTML might look something like this:
 
- .CSRF Token in HTML Meta Tag
 
- [source,html]
 
- ----
 
- <html>
 
- <head>
 
- 	<meta name="_csrf" content="4bfd1575-3ad1-4d21-96c7-4ef2d9f86721"/>
 
- 	<meta name="_csrf_header" content="X-CSRF-TOKEN"/>
 
- 	<!-- ... -->
 
- </head>
 
- <!-- ... -->
 
- </html>
 
- ----
 
- In order to include the CSRF token in the request, you can take advantage of the fact that the `CsrfToken` is exposed as an <<csrf-token-request-handler,`HttpServletRequest` attribute named `_csrf`>>.
 
- The following example does this with a JSP:
 
- .CSRF Token in HTML Meta Tag with Request Attribute
 
- [source,html]
 
- ----
 
- <html>
 
- <head>
 
- 	<meta name="_csrf" content="${_csrf.token}"/>
 
- 	<!-- default header name is X-CSRF-TOKEN -->
 
- 	<meta name="_csrf_header" content="${_csrf.headerName}"/>
 
- 	<!-- ... -->
 
- </head>
 
- <!-- ... -->
 
- </html>
 
- ----
 
- Once the meta tags contain the CSRF token, the JavaScript code can read the meta tags and include the CSRF token as a header.
 
- If you use jQuery, you can do this with the following code:
 
- .Include CSRF Token in AJAX Request
 
- [source,javascript]
 
- ----
 
- $(function () {
 
- 	var token = $("meta[name='_csrf']").attr("content");
 
- 	var header = $("meta[name='_csrf_header']").attr("content");
 
- 	$(document).ajaxSend(function(e, xhr, options) {
 
- 		xhr.setRequestHeader(header, token);
 
- 	});
 
- });
 
- ----
 
- [[csrf-integration-javascript-other]]
 
- ==== Other JavaScript Applications
 
- Another option for JavaScript applications is to include the CSRF token in an HTTP response header.
 
- One way to achieve this is through the use of a `@ControllerAdvice` with the xref:servlet/integrations/mvc.adoc#mvc-csrf-resolver[`CsrfTokenArgumentResolver`].
 
- The following is an example of `@ControllerAdvice` that applies to all controller endpoints in the application:
 
- [[controller-advice]]
 
- .CSRF Token in HTTP Response Header
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @ControllerAdvice
 
- public class CsrfControllerAdvice {
 
- 	@ModelAttribute
 
- 	public void getCsrfToken(HttpServletResponse response, CsrfToken csrfToken) {
 
- 		response.setHeader(csrfToken.getHeaderName(), csrfToken.getToken());
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- @ControllerAdvice
 
- class CsrfControllerAdvice {
 
- 	@ModelAttribute
 
- 	fun getCsrfToken(response: HttpServletResponse, csrfToken: CsrfToken) {
 
- 		response.setHeader(csrfToken.headerName, csrfToken.token)
 
- 	}
 
- }
 
- ----
 
- ======
 
- [NOTE]
 
- ====
 
- Because this `@ControllerAdvice` applies to all endpoints in the application, it will cause the CSRF token to be loaded on every request, which can negate the benefits of <<deferred-csrf-token,deferred tokens>> when using the <<csrf-token-repository-httpsession,`HttpSessionCsrfTokenRepository`>>.
 
- However, this is not usually an issue when using the <<csrf-token-repository-cookie,`CookieCsrfTokenRepository`>>.
 
- ====
 
- [NOTE]
 
- ====
 
- It is important to remember that controller endpoints and controller advice are called _after_ the Spring Security filter chain.
 
- This means that this `@ControllerAdvice` will only be applied if the request passes through the filter chain to your application.
 
- See the configuration for <<csrf-integration-javascript-spa-configuration,single-page applications>> for an example of adding a filter to the filter chain for earlier access to the `HttpServletResponse`.
 
- ====
 
- The CSRF token will now be available in a response header (<<csrf-token-repository-httpsession,`X-CSRF-TOKEN`>> or <<csrf-token-repository-cookie,`X-XSRF-TOKEN`>> by default) for any custom endpoints the controller advice applies to.
 
- Any request to the backend can be used to obtain the token from the response, and a subsequent request can include the token in a request header with the same name.
 
- [[csrf-integration-mobile]]
 
- === Mobile Applications
 
- Like <<csrf-integration-javascript,JavaScript applications>>, mobile applications typically use JSON instead of HTML.
 
- A backend application that _does not_ serve browser traffic may choose to <<disable-csrf,disable CSRF>>.
 
- In that case, no additional work is required.
 
- However, a backend application that also serves browser traffic and therefore _still requires_ CSRF protection may continue to store the `CsrfToken` <<csrf-token-repository-httpsession,in the session>> instead of <<csrf-token-repository-cookie,in a cookie>>.
 
- In this case, a typical pattern for integrating with the backend is to expose a `/csrf` endpoint to allow the frontend (mobile or browser client) to request a CSRF token on demand.
 
- The benefit of using this pattern is that the CSRF token <<deferred-csrf-token,can continue to be deferred>> and only needs to be loaded from the session when a request requires CSRF protection.
 
- The use of a custom endpoint also means the client application can request that a new token be generated on demand (if necessary) by issuing an explicit request.
 
- [TIP]
 
- ====
 
- This pattern can be used for any type of application that requires CSRF protection, not just mobile applications.
 
- While this approach isn't typically required in those cases, it is another option for integrating with a CSRF-protected backend.
 
- ====
 
- The following is an example of the `/csrf` endpoint that makes use of the xref:servlet/integrations/mvc.adoc#mvc-csrf-resolver[`CsrfTokenArgumentResolver`]:
 
- [[csrf-endpoint]]
 
- .The `/csrf` endpoint
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @RestController
 
- public class CsrfController {
 
-     @GetMapping("/csrf")
 
-     public CsrfToken csrf(CsrfToken csrfToken) {
 
-         return csrfToken;
 
-     }
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- @RestController
 
- class CsrfController {
 
-     @GetMapping("/csrf")
 
-     fun csrf(csrfToken: CsrfToken): CsrfToken {
 
-         return csrfToken
 
-     }
 
- }
 
- ----
 
- ======
 
- [NOTE]
 
- ====
 
- You may consider adding `.requestMatchers("/csrf").permitAll()` if the endpoint above is required prior to authenticating with the server.
 
- ====
 
- This endpoint should be called to obtain a CSRF token when the application is launched or initialized (e.g. at load time), and also after authentication success and logout success.
 
- [NOTE]
 
- ====
 
- Refreshing the token after authentication success and logout success is required because the javadoc:org.springframework.security.web.csrf.CsrfAuthenticationStrategy[] and javadoc:org.springframework.security.web.csrf.CsrfLogoutHandler[] will clear the previous token.
 
- The client application will not be able to perform an unsafe HTTP request, such as a POST, without obtaining a fresh token.
 
- ====
 
- Once you've obtained the CSRF token, you will need to include it as an HTTP request header (one of <<csrf-token-repository-httpsession,`X-CSRF-TOKEN`>> or <<csrf-token-repository-cookie,`X-XSRF-TOKEN`>> by default) yourself.
 
- [[csrf-access-denied-handler]]
 
- == Handle `AccessDeniedException`
 
- To handle an `AccessDeniedException` such as `InvalidCsrfTokenException`, you can configure Spring Security to handle these exceptions in any way you like.
 
- For example, you can configure a custom access denied page using the following configuration:
 
- [[csrf-access-denied-handler-configuration]]
 
- .Configure `AccessDeniedHandler`
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		http
 
- 			// ...
 
- 			.exceptionHandling((exceptionHandling) -> exceptionHandling
 
- 				.accessDeniedPage("/access-denied")
 
- 			);
 
- 		return http.build();
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
-     @Bean
 
-     open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
-         http {
 
-             // ...
 
-             exceptionHandling {
 
-                 accessDeniedPage = "/access-denied"
 
-             }
 
-         }
 
-         return http.build()
 
-     }
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <http>
 
- 	<!-- ... -->
 
- 	<access-denied-handler error-page="/access-denied"/>
 
- </http>
 
- ----
 
- ======
 
- [[csrf-testing]]
 
- == CSRF Testing
 
- You can use Spring Security's xref:servlet/test/mockmvc/setup.adoc[testing support] and xref:servlet/test/mockmvc/csrf.adoc[`CsrfRequestPostProcessor`] to test CSRF protection, like this:
 
- [[csrf-testing-example]]
 
- .Test CSRF Protection
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
 
- import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;
 
- import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
 
- import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
 
- @ExtendWith(SpringExtension.class)
 
- @ContextConfiguration(classes = SecurityConfig.class)
 
- @WebAppConfiguration
 
- public class CsrfTests {
 
- 	private MockMvc mockMvc;
 
- 	@BeforeEach
 
- 	public void setUp(WebApplicationContext applicationContext) {
 
- 		this.mockMvc = MockMvcBuilders.webAppContextSetup(applicationContext)
 
- 			.apply(springSecurity())
 
- 			.build();
 
- 	}
 
- 	@Test
 
- 	public void loginWhenValidCsrfTokenThenSuccess() throws Exception {
 
- 		this.mockMvc.perform(post("/login").with(csrf())
 
- 				.accept(MediaType.TEXT_HTML)
 
- 				.param("username", "user")
 
- 				.param("password", "password"))
 
- 			.andExpect(status().is3xxRedirection())
 
- 			.andExpect(header().string(HttpHeaders.LOCATION, "/"));
 
- 	}
 
- 	@Test
 
- 	public void loginWhenInvalidCsrfTokenThenForbidden() throws Exception {
 
- 		this.mockMvc.perform(post("/login").with(csrf().useInvalidToken())
 
- 				.accept(MediaType.TEXT_HTML)
 
- 				.param("username", "user")
 
- 				.param("password", "password"))
 
- 			.andExpect(status().isForbidden());
 
- 	}
 
- 	@Test
 
- 	public void loginWhenMissingCsrfTokenThenForbidden() throws Exception {
 
- 		this.mockMvc.perform(post("/login")
 
- 				.accept(MediaType.TEXT_HTML)
 
- 				.param("username", "user")
 
- 				.param("password", "password"))
 
- 			.andExpect(status().isForbidden());
 
- 	}
 
- 	@Test
 
- 	@WithMockUser
 
- 	public void logoutWhenValidCsrfTokenThenSuccess() throws Exception {
 
- 		this.mockMvc.perform(post("/logout").with(csrf())
 
- 				.accept(MediaType.TEXT_HTML))
 
- 			.andExpect(status().is3xxRedirection())
 
- 			.andExpect(header().string(HttpHeaders.LOCATION, "/login?logout"));
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*
 
- import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*
 
- import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*
 
- import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*
 
- @ExtendWith(SpringExtension::class)
 
- @ContextConfiguration(classes = [SecurityConfig::class])
 
- @WebAppConfiguration
 
- class CsrfTests {
 
- 	private lateinit var mockMvc: MockMvc
 
- 	@BeforeEach
 
- 	fun setUp(applicationContext: WebApplicationContext) {
 
- 		mockMvc = MockMvcBuilders.webAppContextSetup(applicationContext)
 
- 			.apply<DefaultMockMvcBuilder>(springSecurity())
 
- 			.build()
 
- 	}
 
- 	@Test
 
- 	fun loginWhenValidCsrfTokenThenSuccess() {
 
- 		mockMvc.perform(post("/login").with(csrf())
 
- 				.accept(MediaType.TEXT_HTML)
 
- 				.param("username", "user")
 
- 				.param("password", "password"))
 
- 			.andExpect(status().is3xxRedirection)
 
- 			.andExpect(header().string(HttpHeaders.LOCATION, "/"))
 
- 	}
 
- 	@Test
 
- 	fun loginWhenInvalidCsrfTokenThenForbidden() {
 
- 		mockMvc.perform(post("/login").with(csrf().useInvalidToken())
 
- 				.accept(MediaType.TEXT_HTML)
 
- 				.param("username", "user")
 
- 				.param("password", "password"))
 
- 			.andExpect(status().isForbidden)
 
- 	}
 
- 	@Test
 
- 	fun loginWhenMissingCsrfTokenThenForbidden() {
 
- 		mockMvc.perform(post("/login")
 
- 				.accept(MediaType.TEXT_HTML)
 
- 				.param("username", "user")
 
- 				.param("password", "password"))
 
- 			.andExpect(status().isForbidden)
 
- 	}
 
- 	@Test
 
- 	@WithMockUser
 
- 	@Throws(Exception::class)
 
- 	fun logoutWhenValidCsrfTokenThenSuccess() {
 
- 		mockMvc.perform(post("/logout").with(csrf())
 
- 				.accept(MediaType.TEXT_HTML))
 
- 			.andExpect(status().is3xxRedirection)
 
- 			.andExpect(header().string(HttpHeaders.LOCATION, "/login?logout"))
 
- 	}
 
- }
 
- ----
 
- ======
 
- [[disable-csrf]]
 
- == Disable CSRF Protection
 
- By default, CSRF protection is enabled, which affects <<csrf-integration,integrating with the backend>> and <<csrf-testing,testing>> your application.
 
- Before disabling CSRF protection, consider whether it xref:features/exploits/csrf.adoc#csrf-when[makes sense for your application].
 
- You can also consider whether only certain endpoints do not require CSRF protection and configure an ignoring rule, as in the following example:
 
- [[disable-csrf-ignoring-configuration]]
 
- .Ignoring Requests
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
-     @Bean
 
-     public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
-         http
 
-             // ...
 
-             .csrf((csrf) -> csrf
 
-                 .ignoringRequestMatchers("/api/*")
 
-             );
 
-         return http.build();
 
-     }
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
-     @Bean
 
-     open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
-         http {
 
-             // ...
 
-             csrf {
 
-                 ignoringRequestMatchers("/api/*")
 
-             }
 
-         }
 
-         return http.build()
 
-     }
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <http>
 
- 	<!-- ... -->
 
- 	<csrf request-matcher-ref="csrfMatcher"/>
 
- </http>
 
- <b:bean id="csrfMatcher"
 
-     class="org.springframework.security.web.util.matcher.AndRequestMatcher">
 
-     <b:constructor-arg value="#{T(org.springframework.security.web.csrf.CsrfFilter).DEFAULT_CSRF_MATCHER}"/>
 
-     <b:constructor-arg>
 
-         <b:bean class="org.springframework.security.web.util.matcher.NegatedRequestMatcher">
 
-             <b:bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
 
-                 <b:constructor-arg value="/api/*"/>
 
-             </b:bean>
 
-         </b:bean>
 
-     </b:constructor-arg>
 
- </b:bean>
 
- ----
 
- ======
 
- If you need to disable CSRF protection, you can do so using the following configuration:
 
- [[disable-csrf-configuration]]
 
- .Disable CSRF
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		http
 
- 			// ...
 
- 			.csrf((csrf) -> csrf.disable());
 
- 		return http.build();
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
-     @Bean
 
-     open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
-         http {
 
-             // ...
 
-             csrf {
 
-                 disable()
 
-             }
 
-         }
 
-         return http.build()
 
-     }
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <http>
 
- 	<!-- ... -->
 
- 	<csrf disabled="true"/>
 
- </http>
 
- ----
 
- ======
 
- [[csrf-considerations]]
 
- == CSRF Considerations
 
- There are a few special considerations when implementing protection against CSRF attacks.
 
- This section discusses those considerations as they pertain to servlet environments.
 
- See xref:features/exploits/csrf.adoc#csrf-considerations[CSRF Considerations] for a more general discussion.
 
- [[csrf-considerations-login]]
 
- === Logging In
 
- It is important to xref:features/exploits/csrf.adoc#csrf-considerations-login[require CSRF for log in] requests to protect against forging log in attempts.
 
- Spring Security's servlet support does this out of the box.
 
- [[csrf-considerations-logout]]
 
- === Logging Out
 
- It is important to xref:features/exploits/csrf.adoc#csrf-considerations-logout[require CSRF for log out] requests to protect against forging logout attempts.
 
- If CSRF protection is enabled (the default), Spring Security's `LogoutFilter` will only process HTTP POST requests.
 
- This ensures that logging out requires a CSRF token and that a malicious user cannot forcibly log your users out.
 
- The easiest approach is to use a form to log the user out.
 
- If you really want a link, you can use JavaScript to have the link perform a POST (maybe on a hidden form).
 
- For browsers with JavaScript that is disabled, you can optionally have the link take the user to a log out confirmation page that performs the POST.
 
- If you really want to use HTTP GET with logout, you can do so.
 
- However, remember that this is generally not recommended.
 
- For example, the following logs out when the `/logout` URL is requested with any HTTP method:
 
- .Log Out with Any HTTP Method
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		http
 
- 			// ...
 
- 			.logout((logout) -> logout
 
- 				.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
 
- 			);
 
- 		return http.build();
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
-     @Bean
 
-     open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
-         http {
 
-             // ...
 
-             logout {
 
-                 logoutRequestMatcher = AntPathRequestMatcher("/logout")
 
-             }
 
-         }
 
-         return http.build()
 
-     }
 
- }
 
- ----
 
- ======
 
- See the xref:servlet/authentication/logout.adoc[Logout] chapter for more information.
 
- [[considerations-csrf-timeouts]]
 
- === CSRF and Session Timeouts
 
- By default, Spring Security stores the CSRF token in the `HttpSession` using the <<csrf-token-repository-httpsession,`HttpSessionCsrfTokenRepository`>>.
 
- This can lead to a situation where the session expires, leaving no CSRF token to validate against.
 
- We have already discussed xref:features/exploits/csrf.adoc#csrf-considerations-timeouts[general solutions] to session timeouts.
 
- This section discusses the specifics of CSRF timeouts as it pertains to the servlet support.
 
- You can change the storage of the CSRF token to be in a cookie.
 
- For details, see the <<csrf-token-repository-cookie>> section.
 
- If a token does expire, you might want to customize how it is handled by specifying a <<csrf-access-denied-handler,custom `AccessDeniedHandler`>>.
 
- The custom `AccessDeniedHandler` can process the `InvalidCsrfTokenException` any way you like.
 
- [[csrf-considerations-multipart]]
 
- === Multipart (file upload)
 
- We have xref:features/exploits/csrf.adoc#csrf-considerations-multipart[already discussed] how protecting multipart requests (file uploads) from CSRF attacks causes a https://en.wikipedia.org/wiki/Chicken_or_the_egg[chicken and the egg] problem.
 
- When JavaScript is available, we _recommend_ <<csrf-integration-javascript-other,including the CSRF token in an HTTP request header>> to side-step the issue.
 
- If JavaScript is not available, the following sections discuss options for placing the CSRF token in the <<csrf-considerations-multipart-body,body>> and <<csrf-considerations-multipart-url,url>> within a servlet application.
 
- [NOTE]
 
- ====
 
- You can find more information about using multipart forms with Spring in the https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-multipart[Multipart Resolver] section of the Spring reference and the {spring-framework-api-url}org/springframework/web/multipart/support/MultipartFilter.html[`MultipartFilter` javadoc].
 
- ====
 
- [[csrf-considerations-multipart-body]]
 
- ==== Place CSRF Token in the Body
 
- We have xref:features/exploits/csrf.adoc#csrf-considerations-multipart-body[already discussed] the tradeoffs of placing the CSRF token in the body.
 
- In this section, we discuss how to configure Spring Security to read the CSRF from the body.
 
- To read the CSRF token from the body, the `MultipartFilter` is specified before the Spring Security filter.
 
- Specifying the `MultipartFilter` before the Spring Security filter means that there is no authorization for invoking the `MultipartFilter`, which means anyone can place temporary files on your server.
 
- However, only authorized users can submit a file that is processed by your application.
 
- In general, this is the recommended approach because the temporary file upload should have a negligible impact on most servers.
 
- .Configure `MultipartFilter`
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- public class SecurityApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
 
- 	@Override
 
- 	protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
 
- 		insertFilters(servletContext, new MultipartFilter());
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- class SecurityApplicationInitializer : AbstractSecurityWebApplicationInitializer() {
 
-     override fun beforeSpringSecurityFilterChain(servletContext: ServletContext?) {
 
-         insertFilters(servletContext, MultipartFilter())
 
-     }
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <filter>
 
- 	<filter-name>MultipartFilter</filter-name>
 
- 	<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
 
- </filter>
 
- <filter>
 
- 	<filter-name>springSecurityFilterChain</filter-name>
 
- 	<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
 
- </filter>
 
- <filter-mapping>
 
- 	<filter-name>MultipartFilter</filter-name>
 
- 	<url-pattern>/*</url-pattern>
 
- </filter-mapping>
 
- <filter-mapping>
 
- 	<filter-name>springSecurityFilterChain</filter-name>
 
- 	<url-pattern>/*</url-pattern>
 
- </filter-mapping>
 
- ----
 
- ======
 
- [NOTE]
 
- ====
 
- To ensure that `MultipartFilter` is specified before the Spring Security filter with XML configuration, you can ensure the `<filter-mapping>` element of the `MultipartFilter` is placed before the `springSecurityFilterChain` within the `web.xml` file.
 
- ====
 
- [[csrf-considerations-multipart-url]]
 
- ==== Include a CSRF Token in a URL
 
- If letting unauthorized users upload temporary files is not acceptable, an alternative is to place the `MultipartFilter` after the Spring Security filter and include the CSRF as a query parameter in the action attribute of the form.
 
- Since the `CsrfToken` is exposed as an <<csrf-token-request-handler,`HttpServletRequest` attribute named `_csrf`>>, we can use that to create an `action` with the CSRF token in it.
 
- The following example does this with a JSP:
 
- .CSRF Token in Action
 
- [source,html]
 
- ----
 
- <form method="post"
 
- 	action="./upload?${_csrf.parameterName}=${_csrf.token}"
 
- 	enctype="multipart/form-data">
 
- ----
 
- [[csrf-considerations-override-method]]
 
- === HiddenHttpMethodFilter
 
- We have xref:features/exploits/csrf.adoc#csrf-considerations-multipart-body[already discussed] the trade-offs of placing the CSRF token in the body.
 
- In Spring's Servlet support, overriding the HTTP method is done by using {spring-framework-api-url}org/springframework/web/filter/reactive/HiddenHttpMethodFilter.html[`HiddenHttpMethodFilter`].
 
- You can find more information in the https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-rest-method-conversion[HTTP Method Conversion] section of the reference documentation.
 
- [[csrf-further-reading]]
 
- == Further Reading
 
- Now that you have reviewed CSRF protection, consider learning more about xref:servlet/exploits/index.adoc[exploit protection] including xref:servlet/exploits/headers.adoc[secure headers] and the xref:servlet/exploits/firewall.adoc[HTTP firewall] or move on to learning how to xref:servlet/test/index.adoc[test] your application.
 
 
  |