如何使用Spring Security模拟Token认证进行Spring Boot REST控制器单元测试
Spring Security JWT认证REST控制器单元测试方案
下面是几种实用的模拟JWT认证进行控制器单元测试的方法,覆盖不同Spring Security版本场景:
方法一:使用Spring Security 6.1+原生@WithJwt注解
这是最简单的方式,Spring Security 6.1及以上版本提供了专门的JWT测试注解:
- 确保测试依赖中引入
spring-security-test - 测试类上标注
@WebMvcTest(目标控制器.class),启用Web层单元测试并集成Spring Security测试支持 - 在测试方法上添加
@WithJwt,自定义JWT的Claims和权限信息
@WebMvcTest(UserController.class) class UserControllerTest { @Autowired private MockMvc mockMvc; @Test @WithJwt( claims = @JwtClaim(name = "sub", value = "sujay_ghosh"), authorities = {"ROLE_ADMIN", "PERMISSION_EDIT_USER"} ) void getCurrentUserInfo_Authenticated_ReturnsUserDetails() throws Exception { mockMvc.perform(get("/api/users/me")) .andExpect(status().isOk()) .andExpect(jsonPath("$.username").value("sujay_ghosh")); } }
方法二:手动生成JWT并携带请求头
如果需要更贴近真实请求场景,或者使用低版本Spring Security,可以手动构造有效Token并添加到请求头:
- 复用项目中的JWT生成工具类(如
JwtTokenGenerator),或在测试中模拟生成符合规则的Token - 若不想依赖真实Token生成逻辑,可Mock掉JWT解析Bean,让其直接返回认证信息
@WebMvcTest(UserController.class) class UserControllerTest { @Autowired private MockMvc mockMvc; @MockBean private JwtAuthenticationProvider jwtAuthenticationProvider; @Test void updateUser_WithValidJwt_ReturnsSuccess() throws Exception { // 构造模拟认证对象 Authentication auth = new UsernamePasswordAuthenticationToken( "test_user", null, List.of(new SimpleGrantedAuthority("ROLE_EDITOR")) ); // Mock解析逻辑,让指定Token通过验证 String mockToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."; when(jwtAuthenticationProvider.authenticate(any(Authentication.class))) .thenReturn(auth); // 携带Token发送请求 mockMvc.perform(put("/api/users/1") .header("Authorization", "Bearer " + mockToken) .contentType(MediaType.APPLICATION_JSON) .content("{\"name\":\"Updated Name\"}")) .andExpect(status().isOk()); } }
方法三:手动构造JWT认证对象(兼容Spring Security 5.x)
对于Spring Security 5.x版本,可直接构造JwtAuthenticationToken并注入到请求上下文:
@Test void getAdminDashboard_WithJwtAuth_ReturnsDashboardData() throws Exception { // 构造模拟JWT对象 Jwt mockJwt = Jwt.withTokenValue("mock-jwt-token") .header("alg", "HS256") .claim("sub", "admin_user") .claim("roles", "ADMIN") .build(); // 构造JWT认证对象 Authentication auth = new JwtAuthenticationToken( mockJwt, List.of(new SimpleGrantedAuthority("ROLE_ADMIN")) ); // 将认证对象注入请求 mockMvc.perform(get("/api/admin/dashboard") .with(SecurityMockMvcRequestPostProcessors.authentication(auth))) .andExpect(status().isOk()); }
内容的提问来源于stack exchange,提问作者Sujay Ghosh
相关产品推荐
相关产品推荐

