1
0
mirror of synced 2026-08-05 09:47:05 +00:00

Add WebFlux CSRF Protection

Fixes gh-4734
This commit is contained in:
Rob Winch
2017-10-28 20:27:57 -05:00
parent f040bd054d
commit 8da2c7f657
16 changed files with 943 additions and 12 deletions
@@ -26,6 +26,10 @@ import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.server.csrf.CsrfToken;
import org.springframework.security.web.server.csrf.CsrfWebFilter;
import org.springframework.security.web.server.csrf.WebSessionServerCsrfTokenRepository;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
import org.springframework.test.web.reactive.server.MockServerConfigurer;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.reactive.server.WebTestClientConfigurer;
@@ -107,6 +111,35 @@ public class SecurityMockServerConfigurers {
return new UserExchangeMutator(username);
}
public static CsrfMutator csrf() {
return new CsrfMutator();
}
public static class CsrfMutator implements WebTestClientConfigurer, MockServerConfigurer {
@Override
public void afterConfigurerAdded(WebTestClient.Builder builder,
@Nullable WebHttpHandlerBuilder httpHandlerBuilder,
@Nullable ClientHttpConnector connector) {
CsrfWebFilter filter = new CsrfWebFilter();
filter.setRequireCsrfProtectionMatcher( e -> ServerWebExchangeMatcher.MatchResult.notMatch());
httpHandlerBuilder.filters( filters -> filters.add(0, filter));
}
@Override
public void afterConfigureAdded(
WebTestClient.MockServerSpec<?> serverSpec) {
}
@Override
public void beforeServerCreated(WebHttpHandlerBuilder builder) {
}
private CsrfMutator() {}
}
/**
* Updates the WebServerExchange using {@code {@link SecurityMockServerConfigurers#mockUser(UserDetails)}. Defaults to use a
* password of "password" and granted authorities of "ROLE_USER".
@@ -18,15 +18,18 @@ package org.springframework.security.test.web.reactive.server;
import org.junit.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter;
import org.springframework.security.web.server.csrf.CsrfWebFilter;
import org.springframework.test.web.reactive.server.WebTestClient;
import java.security.Principal;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.*;
/**
@@ -36,7 +39,7 @@ import static org.springframework.security.test.web.reactive.server.SecurityMock
public class SecurityMockServerConfigurersTests extends AbstractMockServerConfigurersTests {
WebTestClient client = WebTestClient
.bindToController(controller)
.webFilter(new SecurityContextServerWebExchangeWebFilter())
.webFilter( new CsrfWebFilter(), new SecurityContextServerWebExchangeWebFilter())
.apply(springSecurity())
.configureClient()
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
@@ -144,4 +147,37 @@ public class SecurityMockServerConfigurersTests extends AbstractMockServerConfig
assertPrincipalCreatedFromUserDetails(actual, userBuilder.build());
}
@Test
public void csrfWhenMutateWithThenDisablesCsrf() {
this.client
.post()
.exchange()
.expectStatus().isEqualTo(HttpStatus.FORBIDDEN)
.expectBody().consumeWith( b -> assertThat(new String(b.getResponseBody())).contains("CSRF"));
this.client
.mutateWith(csrf())
.post()
.exchange()
.expectStatus().isOk();
}
@Test
public void csrfWhenGlobalThenDisablesCsrf() {
this.client = WebTestClient
.bindToController(this.controller)
.webFilter(new CsrfWebFilter())
.apply(springSecurity())
.apply(csrf())
.configureClient()
.build();
this.client
.get()
.exchange()
.expectStatus().isOk();
}
}