|
| 1 | +package pro.taskana.example.boot.security; |
| 2 | + |
| 3 | +import jakarta.servlet.http.HttpServletRequest; |
| 4 | +import jakarta.servlet.http.HttpServletResponse; |
| 5 | +import java.util.function.Supplier; |
| 6 | +import org.springframework.security.web.csrf.CsrfToken; |
| 7 | +import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; |
| 8 | +import org.springframework.security.web.csrf.CsrfTokenRequestHandler; |
| 9 | +import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler; |
| 10 | +import org.springframework.util.StringUtils; |
| 11 | + |
| 12 | +final class SpaCsrfTokenRequestHandler extends CsrfTokenRequestAttributeHandler { |
| 13 | + private final CsrfTokenRequestHandler delegate = new XorCsrfTokenRequestAttributeHandler(); |
| 14 | + |
| 15 | + @Override |
| 16 | + public void handle( |
| 17 | + HttpServletRequest request, HttpServletResponse response, Supplier<CsrfToken> csrfToken) { |
| 18 | + /* |
| 19 | + * Always use XorCsrfTokenRequestAttributeHandler to provide BREACH protection of |
| 20 | + * the CsrfToken when it is rendered in the response body. |
| 21 | + */ |
| 22 | + this.delegate.handle(request, response, csrfToken); |
| 23 | + } |
| 24 | + |
| 25 | + @Override |
| 26 | + public String resolveCsrfTokenValue(HttpServletRequest request, CsrfToken csrfToken) { |
| 27 | + /* |
| 28 | + * If the request contains a request header, use CsrfTokenRequestAttributeHandler |
| 29 | + * to resolve the CsrfToken. This applies when a single-page application includes |
| 30 | + * the header value automatically, which was obtained via a cookie containing the |
| 31 | + * raw CsrfToken. |
| 32 | + */ |
| 33 | + if (StringUtils.hasText(request.getHeader(csrfToken.getHeaderName()))) { |
| 34 | + return super.resolveCsrfTokenValue(request, csrfToken); |
| 35 | + } |
| 36 | + /* |
| 37 | + * In all other cases (e.g. if the request contains a request parameter), use |
| 38 | + * XorCsrfTokenRequestAttributeHandler to resolve the CsrfToken. This applies |
| 39 | + * when a server-side rendered form includes the _csrf request parameter as a |
| 40 | + * hidden input. |
| 41 | + */ |
| 42 | + return this.delegate.resolveCsrfTokenValue(request, csrfToken); |
| 43 | + } |
| 44 | +} |
0 commit comments