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

Spring Boot REST服务如何将JUnit 5测试从Basic认证改为Keycloak OAuth2

原有测试适配OAuth2认证体系的修改方案

原有注入身份方案的兼容性说明

  • 原@WithUserDetails注解不能直接使用:该注解是基于用户名密码认证体系的UserDetailsService设计的,当前OAuth2资源服务器依赖的身份对象是JwtAuthenticationToken,和注解生成的UsernamePasswordAuthenticationToken类型不匹配,直接使用会触发401/403权限错误。
  • 手动设置SecurityContext的方案可以调整后使用:只要手动构造符合要求的JwtAuthenticationToken实例注入安全上下文就可以正常运行,不需要真实调用Keycloak申请令牌,适合单元测试场景。

具体修改方案

场景1:单元测试(仅测试Controller逻辑,不依赖Keycloak服务)

推荐使用Spring Security官方提供的模拟注解快速注入身份,不需要改动原有测试的业务逻辑:

  1. 确保已经引入spring-security-test测试依赖,Spring Boot 2.7+版本的spring-boot-starter-test已经默认集成该依赖。
  2. 替换原有@WithUserDetails("admin")注解为@WithMockJwtAuth,示例如下:
// 注解参数里的authorities和你自定义JWT权限转换器输出的角色格式保持一致即可
@WithMockJwtAuth(authorities = {"ROLE_admin"}, claims = @Claims(sub = "admin"))
@Test
void testAdminApi() {
    // 原有测试逻辑不需要修改
}

如果是原手动注入SecurityContext的场景,调整构造逻辑即可,示例代码:

// 1. 构造模拟JWT对象,匹配Keycloak返回的JWT结构
Jwt mockJwt = Jwt.withTokenValue("fake-token-123")
    .header("alg", "RS256")
    .claim("sub", "admin")
    .claim("realm_access", Map.of("roles", List.of("admin")))
    .build();
// 2. 复用你自定义的JWT权限转换器生成权限集合
Collection<GrantedAuthority> authorities = customJwtGrantedAuthoritiesConverter.convert(mockJwt);
// 3. 构造资源服务器识别的认证对象
JwtAuthenticationToken authentication = new JwtAuthenticationToken(mockJwt, authorities);
// 4. 注入安全上下文
SecurityContextHolder.getContext().setAuthentication(authentication);

测试执行完成后记得清空SecurityContext,避免上下文污染其他测试用例。


场景2:集成测试(真实走OAuth2认证流程,依赖已启动的Keycloak服务)

完全模拟真实用户请求流程,适合端到端验证认证授权逻辑:

  1. 在测试配置文件中新增Keycloak相关配置:令牌端点、测试用客户端ID、客户端密钥、测试账号用户名密码。
  2. 测试执行前先向Keycloak申请令牌,请求信息如下:
    • 请求地址:/realms/{你的realm名称}/protocol/openid-connect/token
    • 请求方法:POST
    • 请求体格式:application/x-www-form-urlencoded
    • 必填参数:grant_type=password、client_id=你的客户端ID、client_secret=你的客户端密钥、username=测试用户名、password=测试用户密码
  3. 从返回结果中提取access_token字段,调用业务接口时添加请求头Authorization: Bearer {提取的access_token}即可。

额外注意事项

  • 如果测试用了@WebMvcTest注解,需要在测试类上添加@Import({WebSecurityConfig.class, 自定义JWT权限转换器类名.class}),确保安全配置和权限转换逻辑生效。
  • 如果你的角色校验是直接读取JWT原始字段,需要在模拟JWT时完整填充对应的字段结构,避免校验失败。

内容的提问来源于stack exchange,提问作者neblaz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 09:24:01