Closes #2510 - fixed csrf handling without disabling it
This commit is contained in:
parent
55823186fe
commit
b7dc65d97f
|
@ -75,7 +75,11 @@ public class BootWebSecurityConfigurer {
|
|||
if (enableCsrf) {
|
||||
CookieCsrfTokenRepository csrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
|
||||
csrfTokenRepository.setCookiePath("/");
|
||||
http.csrf(csrf -> csrf.csrfTokenRepository(csrfTokenRepository));
|
||||
http.csrf(
|
||||
csrf ->
|
||||
csrf.csrfTokenRepository(csrfTokenRepository)
|
||||
.csrfTokenRequestHandler(new SpaCsrfTokenRequestHandler()))
|
||||
.addFilterAfter(new CsrfCookieFilter(), SpringSecurityToJaasFilter.class);
|
||||
} else {
|
||||
http.csrf(AbstractHttpConfigurer::disable).httpBasic(Customizer.withDefaults());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package pro.taskana.example.boot.security;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import org.springframework.security.web.csrf.CsrfToken;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
final class CsrfCookieFilter extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(
|
||||
HttpServletRequest request,
|
||||
@SuppressWarnings("NullableProblems") HttpServletResponse response,
|
||||
FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
CsrfToken csrfToken = (CsrfToken) request.getAttribute("_csrf");
|
||||
// Render the token value to a cookie by causing the deferred token to be loaded
|
||||
csrfToken.getToken();
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package pro.taskana.example.boot.security;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.function.Supplier;
|
||||
import org.springframework.security.web.csrf.CsrfToken;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRequestHandler;
|
||||
import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
final class SpaCsrfTokenRequestHandler extends CsrfTokenRequestAttributeHandler {
|
||||
private final CsrfTokenRequestHandler delegate = 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.delegate.handle(request, response, csrfToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveCsrfTokenValue(HttpServletRequest request, CsrfToken csrfToken) {
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
if (StringUtils.hasText(request.getHeader(csrfToken.getHeaderName()))) {
|
||||
return super.resolveCsrfTokenValue(request, 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 this.delegate.resolveCsrfTokenValue(request, csrfToken);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue