SpringBoot 2.1升级后WebTestClient测试遇403问题求助
这个问题的核心在于你创建WebTestClient的方式——bindToServer()是一个纯HTTP客户端,完全独立于你的Spring测试上下文,所以你做的任何安全配置修改(比如排除SecurityAutoConfiguration)都不会作用到它身上。
Spring Boot 2.1提到的「安全配置现已应用于WebTestClient」,指的是与Spring测试上下文绑定的WebTestClient实例(比如通过@AutoConfigureWebTestClient注入,或者用bindToApplicationContext()创建),这类实例会自动集成Spring Security的配置,包括测试时的认证模拟能力;而bindToServer()创建的客户端相当于一个外部调用工具,直接请求运行中的服务器,服务器会用完整的生产级安全配置校验请求,自然返回403。
解决方法分两种情况:
情况1:希望利用测试上下文的安全配置(推荐)
放弃bindToServer(),改用与测试上下文绑定的WebTestClient,这样你的安全配置修改(禁用、模拟认证等)才会生效:
- 用
@AutoConfigureWebTestClient注解自动注入配置好的WebTestClient:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureWebTestClient public class YourRestTests { @Autowired private WebTestClient webTestClient; @Test void testProtectedEndpoint() { // 如果需要模拟认证,直接用Spring Security提供的扩展方法 webTestClient.get().uri("/protected-endpoint") .with(SecurityMockMvcRequestPostProcessors.user("test-user").roles("ADMIN")) .exchange() .expectStatus().isOk(); } }
- 或者手动绑定到应用上下文:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class YourRestTests { @Autowired private ApplicationContext context; private WebTestClient webTestClient; @BeforeEach void setUp() { webTestClient = WebTestClient.bindToApplicationContext(context).build(); } // 测试方法同上 }
情况2:必须使用bindToServer()(外部HTTP调用场景)
如果一定要用独立的HTTP客户端测试,那你需要在请求中带上符合服务器安全要求的认证信息,比如Basic Auth头、JWT Token等,相当于模拟真实用户的请求:
// 假设服务器用Basic Auth String basicAuth = "Basic " + Base64.getEncoder().encodeToString("username:password".getBytes()); WebTestClient client = WebTestClient.bindToServer() .baseUrl("http://localhost:" + port) .defaultHeader(HttpHeaders.AUTHORIZATION, basicAuth) .build(); // 发送请求 client.get().uri("/protected-endpoint") .exchange() .expectStatus().isOk();
补充说明
你之前尝试排除SecurityAutoConfiguration无效,就是因为bindToServer()的客户端和测试上下文完全脱钩——它请求的是已经启动的完整应用服务器,服务器加载的是完整的配置,包括Spring Security,测试上下文里的排除配置根本影响不到运行中的服务器。
内容的提问来源于stack exchange,提问作者naitsabes

