Spring @WebMvcTest测试OpenAPI生成的@PreAuthorize控制器返回401异常
问题原因
在@WebMvcTest切片测试环境下,方法级安全的核心组件未被正确初始化,导致@PreAuthorize注解的权限校验逻辑没有执行。@WebMvcTest默认仅加载Web层相关Bean(如@RestController),不会自动导入全局的Spring Security配置类(即你的RestSecurityConfiguration),而@EnableMethodSecurity注解正是在这个配置类中启用方法安全的关键——它负责注册MethodSecurityInterceptor等切面组件,没有这些组件,@PreAuthorize的校验就不会生效。
此时虽然你传入了已认证的Authentication对象,但由于方法安全校验未触发,结合OAuth2资源服务器的配置逻辑,最终返回了401而非预期的403。而改用HttpSecurity的requestMatchers配置时,权限校验是在过滤器链层面执行的,只要SecurityFilterChainBean被加载就能正常工作,因此测试可以通过。
解决方案
方案1:导入全局Security配置类
在测试类中显式导入RestSecurityConfiguration,确保@EnableMethodSecurity和相关安全组件被加载:
@WebMvcTest(PingController.class) @Import({PingApiController.class, RestSecurityConfiguration.class}) class PingControllerTest extends AbstractControllerTest { @MockBean private JwtAuthConverter jwtAuthConverter; // Mock配置类依赖的JwtAuthConverter // ... 测试代码 }
方案2:在测试类中直接启用方法安全
如果不想导入完整的全局配置,可以在测试类上直接添加@EnableMethodSecurity注解,单独启用方法级安全:
@WebMvcTest(PingController.class) @Import({PingApiController.class}) @EnableMethodSecurity class PingControllerTest extends AbstractControllerTest { // ... 测试代码 }
方案3:确认认证对象权限格式
你的测试代码中已经将权限转为ROLE_wrong-role,这与hasRole('ping')自动添加ROLE_前缀的逻辑匹配,这部分无需修改,只需确保方法安全生效后,该权限校验逻辑能被触发。
验证
修改后重新运行测试,@PreAuthorize的权限校验会正常执行,当角色不匹配时,会返回预期的HTTP 403状态码。
内容的提问来源于stack exchange,提问作者Robert Strauch

