如何使用JUnit测试Spring应用中JWT认证保护的安全接口?报403如何解决
问题排查与解决方案
错误原因
- 权限字符串不匹配:安全配置中要求的接口访问权限值为
VT、Admin、User、Developer,但你在secureBean中定义的权限是VT_SCOPE、ADMIN_SCOPE这类常量名称,和配置要求的权限值完全不一致,直接导致权限校验失败返回403。 - 测试注解与认证体系不匹配:你使用的
@WithUserDetails是面向普通用户名密码认证体系的测试注解,而当前项目使用的是OAuth2 JWT资源服务器认证,该注解注入的认证上下文不符合JWT认证的校验逻辑,无法被安全框架正确识别。
修复方案
方案1:使用JWT专属测试注解(推荐,和生产认证逻辑一致)
无需保留自定义的secureBean,直接使用Spring Security测试包提供的@WithMockJwtAuth注解模拟JWT认证上下文即可,步骤如下:
- 确认项目依赖中已引入
spring-security-test组件 - 测试用例修改为如下代码:
import org.springframework.security.test.context.support.WithMockJwtAuth; @Test @WithMockJwtAuth(authorities = {"VT", "User"}) public void addForumTest() throws Exception { ForumQueryDto forumQueryDto = new ForumQueryDto("1","Query 1","Query 1 Desc",userDto,currentTime,repliesDto); Mockito.when(forumService.insertQuery(Mockito.any(ForumQueryDto.class))).thenReturn(forumQueryDto); MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/user/forum/add") .contentType("application/json") .content(objectMapper.writeValueAsString(forumQueryDto))) .andReturn(); MockHttpServletResponse response = result.getResponse(); assertEquals(HttpStatus.CREATED.value(), response.getStatus()); }
方案2:保留@WithUserDetails写法的修复步骤
- 修正
secureBean中的权限值,和安全配置保持一致:
@Bean("secureBean") public UserDetailsService userDetailsService() { GrantedAuthority authority = new SimpleGrantedAuthority("VT"); GrantedAuthority authority1 = new SimpleGrantedAuthority("Admin"); GrantedAuthority authority2 = new SimpleGrantedAuthority("User"); GrantedAuthority authority3 = new SimpleGrantedAuthority("Developer"); UserDetails userDetails = new User("ram", "ram123", Arrays.asList(authority, authority1, authority2, authority3)); return new InMemoryUserDetailsManager(Arrays.asList(userDetails)); }
- 确保测试类上添加
@AutoConfigureMockMvc注解,且MockMvc实例通过@Autowired注入,测试上下文已加载安全配置类。
内容的提问来源于stack exchange,提问作者Sugata Kar
相关产品推荐
相关产品推荐

