Skip to content
This repository was archived by the owner on Dec 19, 2023. It is now read-only.

Commit 6be4a07

Browse files
fix(#487): csrf is now supported with Playground on Webflux
1 parent 1b93759 commit 6be4a07

File tree

6 files changed

+71
-2
lines changed

6 files changed

+71
-2
lines changed

playground-spring-boot-autoconfigure/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ dependencies{
2222
implementation "org.springframework.boot:spring-boot-autoconfigure"
2323
compileOnly "org.springframework.boot:spring-boot-starter-web"
2424
compileOnly "org.springframework.boot:spring-boot-starter-webflux"
25+
compileOnly "org.springframework.boot:spring-boot-starter-security"
2526
implementation "org.springframework.boot:spring-boot-starter-thymeleaf"
2627
implementation "org.springframework.boot:spring-boot-starter-validation"
2728

2829
testImplementation "org.springframework.boot:spring-boot-starter-web"
2930
testImplementation "org.springframework.boot:spring-boot-starter-webflux"
3031
testImplementation "org.springframework.boot:spring-boot-starter-test"
3132
testImplementation "org.springframework.boot:spring-boot-starter-security"
33+
testImplementation "org.springframework.security:spring-security-test"
3234
testImplementation "org.jsoup:jsoup:$LIB_JSOUP_VER"
3335
}
3436

playground-spring-boot-autoconfigure/src/main/java/graphql/kickstart/playground/boot/PlaygroundController.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
import java.nio.file.Paths;
1111

12+
import static java.util.Objects.nonNull;
13+
1214
@Controller
1315
@RequiredArgsConstructor
1416
public class PlaygroundController {
@@ -38,7 +40,9 @@ public String playground(final Model model, final @RequestAttribute(value = _CSR
3840
}
3941
model.addAttribute("pageTitle", propertiesConfiguration.getPlayground().getPageTitle());
4042
model.addAttribute("properties", objectMapper.valueToTree(propertiesConfiguration.getPlayground()));
41-
model.addAttribute(_CSRF, csrf);
43+
if (nonNull(csrf)) {
44+
model.addAttribute(_CSRF, csrf);
45+
}
4246
return "playground";
4347
}
4448

playground-spring-boot-autoconfigure/src/main/java/graphql/kickstart/playground/boot/PlaygroundWebFluxAutoConfiguration.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package graphql.kickstart.playground.boot;
22

33
import lombok.RequiredArgsConstructor;
4+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
45
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
56
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
7+
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
8+
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
69
import org.springframework.context.ApplicationContext;
710
import org.springframework.context.annotation.Bean;
811
import org.springframework.context.annotation.Configuration;
12+
import org.springframework.context.annotation.Import;
913
import org.springframework.core.io.ClassPathResource;
1014
import org.springframework.web.reactive.config.ViewResolverRegistry;
1115
import org.springframework.web.reactive.config.WebFluxConfigurer;
@@ -20,6 +24,7 @@
2024
import java.nio.charset.StandardCharsets;
2125

2226
@Configuration
27+
@Import(PlaygroundWebFluxControllerAdvice.class)
2328
@ConditionalOnClass(WebFluxConfigurer.class)
2429
@ConditionalOnProperty(value = "graphql.playground.enabled", havingValue = "true", matchIfMissing = true)
2530
@RequiredArgsConstructor
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package graphql.kickstart.playground.boot;
2+
3+
import lombok.NoArgsConstructor;
4+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
5+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
6+
import org.springframework.security.web.reactive.result.view.CsrfRequestDataValueProcessor;
7+
import org.springframework.security.web.server.csrf.CsrfToken;
8+
import org.springframework.web.bind.annotation.ControllerAdvice;
9+
import org.springframework.web.bind.annotation.ModelAttribute;
10+
import org.springframework.web.server.ServerWebExchange;
11+
import reactor.core.publisher.Mono;
12+
13+
@NoArgsConstructor
14+
@ControllerAdvice
15+
@ConditionalOnClass({ CsrfToken.class, CsrfRequestDataValueProcessor.class })
16+
@ConditionalOnBean(CsrfRequestDataValueProcessor.class)
17+
public class PlaygroundWebFluxControllerAdvice {
18+
19+
@ModelAttribute(CsrfRequestDataValueProcessor.DEFAULT_CSRF_ATTR_NAME)
20+
public Mono<CsrfToken> getCsrfToken(final ServerWebExchange exchange) {
21+
return exchange.getAttributeOrDefault(CsrfToken.class.getName(), Mono.empty());
22+
}
23+
}

playground-spring-boot-autoconfigure/src/test/java/graphql/kickstart/playground/boot/PlaygroundTestConfig.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
import com.fasterxml.jackson.databind.ObjectMapper;
44
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
55
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
6+
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
67
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
78
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
89
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
910
import org.springframework.test.context.ContextConfiguration;
1011

11-
@EnableAutoConfiguration
12+
@EnableAutoConfiguration(exclude = WebFluxAutoConfiguration.class)
1213
@EnableWebSecurity
1314
@ContextConfiguration(classes = {PlaygroundAutoConfiguration.class, ObjectMapper.class,
1415
ThymeleafAutoConfiguration.class})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package graphql.kickstart.playground.boot.webflux;
2+
3+
import graphql.kickstart.playground.boot.PlaygroundTestHelper;
4+
import org.junit.jupiter.api.Test;
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
7+
import org.springframework.boot.test.context.SpringBootTest;
8+
import org.springframework.test.web.reactive.server.WebTestClient;
9+
10+
import java.nio.charset.StandardCharsets;
11+
12+
import static org.assertj.core.api.Assertions.assertThat;
13+
14+
@SpringBootTest(classes = PlaygroundWebFluxTestConfig.class)
15+
@AutoConfigureWebTestClient
16+
public class PlaygroundWebFluxCSRFTest {
17+
18+
@Autowired
19+
private WebTestClient webTestClient;
20+
21+
@Test
22+
void shouldLoadCSRFData() {
23+
// WHEN
24+
final byte[] actual = webTestClient.get().uri(PlaygroundTestHelper.DEFAULT_PLAYGROUND_ENDPOINT)
25+
.exchange()
26+
.expectStatus().isOk()
27+
.expectBody().returnResult().getResponseBody();
28+
// THEN
29+
assertThat(actual).isNotNull();
30+
assertThat(new String(actual, StandardCharsets.UTF_8))
31+
.contains("let csrf = {\"token\":")
32+
.contains("\"parameterName\":\"_csrf\",\"headerName\":\"X-CSRF-TOKEN\"}");
33+
}
34+
}

0 commit comments

Comments
 (0)