From 14007d21731ddc152e22266158a5eaacf0dd895c Mon Sep 17 00:00:00 2001 From: Hao Date: Sun, 24 Nov 2024 07:55:28 +0800 Subject: [PATCH] improve CSRF Token Handling for SPA (#27908) --- .../SecurityConfiguration_imperative.java.ejs | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/generators/spring-boot/templates/src/main/java/_package_/config/SecurityConfiguration_imperative.java.ejs b/generators/spring-boot/templates/src/main/java/_package_/config/SecurityConfiguration_imperative.java.ejs index 2608def03185..ca06baf0c336 100644 --- a/generators/spring-boot/templates/src/main/java/_package_/config/SecurityConfiguration_imperative.java.ejs +++ b/generators/spring-boot/templates/src/main/java/_package_/config/SecurityConfiguration_imperative.java.ejs @@ -45,9 +45,6 @@ import org.springframework.security.web.SecurityFilterChain; <%_ if (!skipClient || authenticationUsesCsrf) { _%> import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; <%_ } _%> -<%_ if (authenticationUsesCsrf) { _%> -import tech.jhipster.web.filter.CookieCsrfFilter; -<%_ } _%> <%_ if (!skipClient) { _%> import <%= packageName %>.web.filter.SpaWebFilter; <%_ } _%> @@ -175,11 +172,6 @@ public class SecurityConfiguration { <%_ if (!skipClient) { _%> .addFilterAfter(new SpaWebFilter(), BasicAuthenticationFilter.class) <%_ } _%> -<%_ if (!applicationTypeMicroservice) { _%> - <%_ if (authenticationUsesCsrf) { _%> - .addFilterAfter(new CookieCsrfFilter(), BasicAuthenticationFilter.class) - <%_ } _%> -<%_ } _%> <%_ if (!skipClient) { _%> .headers(headers -> headers .contentSecurityPolicy(csp -> csp.policyDirectives(jHipsterProperties.getSecurity().getContentSecurityPolicy())) @@ -376,15 +368,15 @@ public class SecurityConfiguration { <%_ if (authenticationUsesCsrf && !applicationTypeMicroservice) { _%> /** - * Custom CSRF handler to provide BREACH protection. + * Custom CSRF handler to provide BREACH protection for Single-Page Applications (SPA). * * @see Spring Security Documentation - Integrating with CSRF Protection * @see JHipster - use customized SpaCsrfTokenRequestHandler to handle CSRF token * @see CSRF protection not working with Spring Security 6 */ - static final class SpaCsrfTokenRequestHandler extends CsrfTokenRequestAttributeHandler { - - private final CsrfTokenRequestHandler delegate = new XorCsrfTokenRequestAttributeHandler(); + static 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) { @@ -392,7 +384,10 @@ public class SecurityConfiguration { * Always use XorCsrfTokenRequestAttributeHandler to provide BREACH protection of * the CsrfToken when it is rendered in the response body. */ - this.delegate.handle(request, response, csrfToken); + this.xor.handle(request, response, csrfToken); + + // Render the token value to a cookie by causing the deferred token to be loaded. + csrfToken.get(); } @Override @@ -404,7 +399,7 @@ public class SecurityConfiguration { * raw CsrfToken. */ if (StringUtils.hasText(request.getHeader(csrfToken.getHeaderName()))) { - return super.resolveCsrfTokenValue(request, csrfToken); + return this.plain.resolveCsrfTokenValue(request, csrfToken); } /* * In all other cases (e.g. if the request contains a request parameter), use @@ -412,7 +407,7 @@ public class SecurityConfiguration { * when a server-side rendered form includes the _csrf request parameter as a * hidden input. */ - return this.delegate.resolveCsrfTokenValue(request, csrfToken); + return this.xor.resolveCsrfTokenValue(request, csrfToken); } } <%_ } _%>