Spring WebFlux 请求主体在测试中为空
Posted
技术标签:
【中文标题】Spring WebFlux 请求主体在测试中为空【英文标题】:Spring WebFlux Request Principal is null in test 【发布时间】:2021-03-03 03:15:37 【问题描述】:我们有一个库,它为我们的请求提供了一个自定义过滤器,我们用它来将有关请求的信息写入我们的日志。我们以前只需要 servlet 支持,但现在需要添加 webflux 支持。我创建了一个新的 WebFilter,它按预期工作。
但是,尝试测试这个新过滤器很困难。我们在日志的用户信息请求中依赖于主体,但在测试期间,它始终为空。我尝试了很多东西,包括以下示例:https://docs.spring.io/spring-security/site/docs/5.1.0.RELEASE/reference/html/test-webflux.html
我的过滤器:
package com.project.utils.security.request.logging.config.autoconfig;
import com.project.utils.logging.LoggingUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
public class ReactiveRequestLoggingFilter implements WebFilter
private static final Logger logger = LoggerFactory.getLogger(ReactiveRequestLoggingFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain)
return serverWebExchange
.getPrincipal()
.flatMap(
principal ->
LoggingUtil loggingUtil =
new LoggingUtil(serverWebExchange.getRequest(), principal.getName());
loggingUtil.setEvent("Http Request");
logger.info(loggingUtil.toString());
return webFilterChain.filter(serverWebExchange);
);
我的测试:
package com.project.utils.security.request.logging.config.autoconfig;
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockUser;
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity;
import com.project.utils.security.request.logging.config.testcontrollers.ReactiveTestController;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.reactive.server.WebTestClient;
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = ReactiveTestController.class)
class ReactiveRequestLoggingFilterTest
@Autowired ReactiveTestController controller;
ReactiveRequestLoggingFilter filter = new ReactiveRequestLoggingFilter();
@Test
void test()
WebTestClient client =
WebTestClient.bindToController(controller)
.webFilter(filter)
.apply(springSecurity())
.configureClient()
.build()
.mutateWith(mockUser("User"));
client
.get()
.uri("/test")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("GET");
我用于测试的控制器:
package com.project.utils.security.request.logging.config.testcontrollers;
import com.project.utils.security.request.logging.config.annotations.EnableReactiveRequestLogging;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/test")
@EnableReactiveRequestLogging
public class ReactiveTestController
@GetMapping
Mono<ResponseEntity<String>> get()
return Mono.just(ResponseEntity.ok("GET"));
我们使用的是 Spring Boot 2.1,它使用 Spring Security 5.1。就像我说的,实际的功能是有效的,但是我们需要为它编写测试,我不知道如何让委托人进入请求。
谢谢!
【问题讨论】:
而您需要通过身份验证才能访问/test?否则,Spring Security 不会应用于该特定端点,那么在向该端点发出请求时就没有主体的概念。 我需要对其进行身份验证,因为过滤器依赖于存在的主体。 【参考方案1】:好的,从这个答案中找到了一个可行的解决方案:https://***.com/a/55426458/1370823
我的最终测试如下:
package com.project.utils.security.request.logging.config.autoconfig;
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity;
import com.project.utils.security.request.logging.config.testcontrollers.ReactiveTestController;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.reactive.server.WebTestClient;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = ReactiveTestController.class, ReactiveRequestLoggingFilter.class)
@WebFluxTest(controllers = ReactiveTestController.class)
@WithMockUser(value = "Test User", username = "TestUser")
class ReactiveRequestLoggingFilterTest
@Autowired ReactiveTestController controller;
@Autowired ReactiveRequestLoggingFilter filter;
@Test
void test()
WebTestClient client =
WebTestClient.bindToController(controller)
.webFilter(new SecurityContextServerWebExchangeWebFilter())
.webFilter(filter)
.apply(springSecurity())
.build();
client
.get()
.uri("/test")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("GET");
【讨论】:
以上是关于Spring WebFlux 请求主体在测试中为空的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security WebFlux - 带有身份验证的主体
`NativeWebRequest` 在使用 Spring Boot 的传入请求中为空
Webflux 请求处理程序中 ServerRequest 返回的 null 主体