You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 19:07:27