Spring Boot安全API集成测试403错误排查求助
问题排查与解决方案
核心原因
你用@WithMockUser做测试,但应用是基于OAuth2资源服务器JWT认证,两者认证机制不兼容:
@WithMockUser模拟的是基于Session的普通认证,生成的是UsernamePasswordAuthenticationToken- 你的安全配置针对JWT认证,Spring Security会期望认证对象是
JwtAuthenticationToken,权限解析逻辑也是从JWT声明中提取,所以@WithMockUser的角色不会被JWT权限校验逻辑识别,最终返回403。
解决方案
方案1:用Spring Security OAuth2测试专用的@WithMockJwt
Spring Security 5.2+(Spring Boot 2.3.7对应版本支持)提供了@WithMockJwt注解,适配JWT资源服务器场景:
- 确保测试依赖包含
spring-security-test(Spring Boot 2.3.7默认已集成) - 替换
@WithMockUser为@WithMockJwt,根据安全配置指定对应权限:
@WebMvcTest(YourTargetController.class) @Import(OktaWebSecurityConfig.class) // 确保加载安全配置类 class AdminEndpointTest { @Autowired private MockMvc mockMvc; @Test @WithMockJwt(authorities = "admin") // 若安全配置用hasAuthority("admin") // 若用hasRole("admin"),则写authorities = "ROLE_admin" void testAdminAccessible() throws Exception { mockMvc.perform(get("/my-link/test-path")) .andExpect(status().isOk()); } }
方案2:手动构造JwtAuthenticationToken注入上下文
如果需要更灵活的JWT模拟,可以手动构建认证对象:
@Test void testAdminEndpoint() throws Exception { // 构造权限集合 Collection<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("admin"); // 模拟JWT核心信息 Jwt mockJwt = Jwt.withTokenValue("fake-jwt-token") .header("alg", "HS256") .claim("sub", "admin-account") .build(); // 构造JWT认证token JwtAuthenticationToken authToken = new JwtAuthenticationToken(mockJwt, authorities); // 注入到Security上下文 SecurityContextHolder.getContext().setAuthentication(authToken); mockMvc.perform(get("/my-link/test-path")) .andExpect(status().isOk()); }
关键检查点
- 核对安全配置的权限判断规则:
- 若用
antMatchers("/my-link/**").hasRole("admin"),权限值需要是ROLE_admin(Spring Security会自动给role添加ROLE_前缀) - 若用
antMatchers("/my-link/**").hasAuthority("admin"),直接用admin作为权限值即可
- 若用
- 确保测试类通过
@WebMvcTest或@Import正确加载了OktaWebSecurityConfig,否则安全规则不会在测试中生效
内容的提问来源于stack exchange,提问作者tjholmes66
相关产品推荐
相关产品推荐

