Skip to content

Instantly share code, notes, and snippets.

@mpalourdio
Last active February 18, 2025 12:20
Show Gist options
  • Save mpalourdio/6a6afabcc4824b08e8f580d32e11caef to your computer and use it in GitHub Desktop.
Save mpalourdio/6a6afabcc4824b08e8f580d32e11caef to your computer and use it in GitHub Desktop.
Spring Security : MockMvc tests with XorCsrfTokenRequestAttributeHandler - Custom RequestPostProcessor
package xx.xx.xxxxxxx.xxxxxxx.requestpostprocessor;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.test.web.support.WebTestUtils;
import org.springframework.test.web.servlet.request.RequestPostProcessor;
public final class XorCsrfRequestPostProcessor implements RequestPostProcessor {
static final String XSRF_TOKEN_COOKIE_NAME = "XSRF-TOKEN";
static final String X_XSRF_TOKEN_HEADER_NAME = "X-XSRF-TOKEN";
private XorCsrfRequestPostProcessor() {
}
@Override
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
HttpServletResponse response = new MockHttpServletResponse();
var csrfTokenRepository = WebTestUtils.getCsrfTokenRepository(request);
var csrfTokenRequestHandler = WebTestUtils.getCsrfTokenRequestHandler(request);
var deferredCsrfToken = csrfTokenRepository.loadDeferredToken(request, response);
csrfTokenRequestHandler.handle(request, response, deferredCsrfToken::get);
var cookie = new Cookie(XSRF_TOKEN_COOKIE_NAME, deferredCsrfToken.get().getToken());
request.setCookies(cookie);
request.addHeader(X_XSRF_TOKEN_HEADER_NAME, deferredCsrfToken.get().getToken());
return request;
}
/**
* Provides ability to use XorCsrfTokenRequestAttributeHandler as RequestPostProcessor for mockMvc tests
* <p>
* <ul>
* <li>Fixes:
* <ul>
* <li><a href="https://stackoverflow.com/questions/74729765/csrf-in-tests-stopped-working-with-spring-boot-3-and-spring-security-6">StackOverFlow</a>
* <li><a href="https://github.com/spring-projects/spring-security/issues/12774">GitHub Issue</a>
* </ul>
* </ul>
* </ul>
* <pre>
* <p>Example:</p>
* &#064;Test
* void postRequestTest() throws Exception {
* mockMvc.perform(post("/api/post")
* .with(xorCsrf()))
* .andReturn();
* </<pre>
*/
public static XorCsrfRequestPostProcessor xorCsrf() {
return new XorCsrfRequestPostProcessor();
}
}
package xx.xx.xxxxxxx.xxxxxxx.requestpostprocessor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.test.web.support.WebTestUtils;
import java.util.Objects;
import static xx.xx.xxxxxxx.xxxxxxx.XorCsrfRequestPostProcessor.*;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
class XorCsrfRequestPostProcessorTest {
@Test
void testHasXsrfTokenCookie() {
var xorCsrf = xorCsrf();
var mockHttpServletRequest = xorCsrf.postProcessRequest(new MockHttpServletRequest());
var cookies = asList(Objects.requireNonNull(mockHttpServletRequest.getCookies()));
var deferredCsrfToken = getDeferredCsrfToken(mockHttpServletRequest);
assertThat(cookies.getFirst().getName()).isEqualTo(XSRF_TOKEN_COOKIE_NAME);
assertThat(cookies.getFirst().getValue()).isEqualTo(deferredCsrfToken);
}
@Test
void testHasXsrfTokenHeader() {
var xorCsrf = xorCsrf();
var mockHttpServletRequest = xorCsrf.postProcessRequest(new MockHttpServletRequest());
var header = mockHttpServletRequest.getHeader(X_XSRF_TOKEN_HEADER_NAME);
var deferredCsrfToken = getDeferredCsrfToken(mockHttpServletRequest);
assertThat(header).isEqualTo(deferredCsrfToken);
}
private static String getDeferredCsrfToken(HttpServletRequest mockHttpServletRequest) {
var csrfTokenRepository = WebTestUtils.getCsrfTokenRepository(mockHttpServletRequest);
HttpServletResponse response = new MockHttpServletResponse();
var deferredCsrfToken = csrfTokenRepository.loadDeferredToken(mockHttpServletRequest, response);
return deferredCsrfToken.get().getToken();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment