【问题标题】:Spring WebFlux Request Principal is null in testSpring WebFlux 请求主体在测试中为空
【发布时间】: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 不会应用于该特定端点,那么在向该端点发出请求时就没有主体的概念。
  • 我需要对其进行身份验证,因为过滤器依赖于存在的主体。

标签: spring-boot spring-security spring-webflux


【解决方案1】:

好的,从这个答案中找到了一个可行的解决方案:https://stackoverflow.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");
  }
}

【讨论】:

    猜你喜欢
    • 2020-10-17
    • 2017-12-27
    • 2021-06-23
    • 2020-12-11
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-02
    相关资源
    最近更新 更多