Spring Boot升级后WebMvcTest中无授权GET请求返回302而非401的问题解决咨询
解决Spring Boot 2.4+ WebMvcTest中未认证GET请求返回302而非401的问题
这问题我之前帮同事排查过类似的,核心原因是Spring Boot 2.4.x版本调整了OAuth2相关自动配置在测试环境下的行为——当你用@WebMvcTest时,默认会加载OAuth2客户端的配置逻辑,而非完整的资源服务器配置。未认证的GET请求(默认不触发CSRF检查)会被引导到授权服务器登录页面(也就是你看到的/oauth2/authorization/keycloak),而POST请求因为CSRF校验失败直接返回403,这就导致了测试和生产环境的行为差异。
下面给你几个可行的解决方案:
方案1:自定义测试用安全配置,强制返回401
你可以写一个仅用于测试的安全配置类,覆盖默认的OAuth2客户端重定向逻辑,指定未认证请求直接返回401状态码:
@Configuration public class TestSecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http // 要求所有请求都需要认证 .authorizeRequests(auth -> auth.anyRequest().authenticated()) // 设置未认证时直接返回401,而非重定向 .exceptionHandling(ex -> ex.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)) ) // 禁用OAuth2登录的重定向逻辑 .oauth2Login().disable(); return http.build(); } }
然后在你的测试类上添加@Import(TestSecurityConfig.class),让测试上下文加载这个配置:
@WebMvcTest(YourController.class) @ContextConfiguration(classes = {YourMapper.class, TestSecurityConfig.class}) @AutoConfigureMockMvc public class YourControllerTest { // 你的测试代码... }
方案2:在测试配置中禁用OAuth2登录自动配置
如果不想写自定义配置,也可以直接在测试类上排除OAuth2登录的自动配置类,避免触发重定向逻辑:
@WebMvcTest(YourController.class) @ContextConfiguration(classes = YourMapper.class) @AutoConfigureMockMvc @EnableAutoConfiguration(exclude = OAuth2LoginAutoConfiguration.class) public class YourControllerTest { // 你的测试代码... }
方案3:通过MockMvc模拟资源服务器认证逻辑
另一种思路是在测试中手动配置MockMvc,让它使用资源服务器的认证入口点。你可以通过@MockBean替换默认的AuthenticationEntryPoint:
@WebMvcTest(YourController.class) @ContextConfiguration(classes = YourMapper.class) @AutoConfigureMockMvc public class YourControllerTest { @MockBean private AuthenticationEntryPoint authenticationEntryPoint; @BeforeEach void setUp() throws Exception { // 配置未认证时返回401 doAnswer(invocation -> { HttpServletResponse response = invocation.getArgument(1); response.setStatus(HttpStatus.UNAUTHORIZED.value()); return null; }).when(authenticationEntryPoint).commence(any(), any(), any()); } // 你的测试代码... }
为什么POST请求正常返回403?
顺便解释下这个差异:Spring Security默认对POST请求启用CSRF校验,未认证的POST请求会直接触发CSRF校验失败,返回403;而GET请求默认不校验CSRF,所以会走OAuth2客户端的登录重定向流程,导致返回302。
内容的提问来源于stack exchange,提问作者tybur
相关产品推荐
相关产品推荐

