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

集成Keycloak与Spring的WSO2 API调用权限验证失败求助

实现WSO2 APIM + Keycloak + Spring Boot的双重权限验证

要同时验证应用令牌(WSO2订阅令牌)和用户权限(Keycloak用户令牌),核心是让WSO2负责应用级的订阅校验,并将用户令牌传递给后端Spring Boot服务,由Spring Security完成用户角色的校验。以下是具体实现步骤:

一、WSO2 APIM端配置:转发用户令牌并校验应用权限

  1. 配置API转发用户令牌

    • 登录WSO2 APIM Publisher,打开目标API,进入「Manage」→「Runtime Configurations」
    • 在「Endpoint Configurations」的「Headers」区域,添加自定义请求头(比如X-User-JWT),值设置为前端传入的用户令牌变量(建议前端用自定义头传递用户令牌,避免和WSO2的应用令牌冲突)
    • 保存API配置并重新发布
  2. 确保Keycloak密钥管理器的令牌校验能力

    • 在WSO2的「Key Managers」页面,打开已配置的Keycloak密钥管理器
    • 勾选「Enable OAuth2 Introspection」,配置Keycloak的令牌 introspection 端点(格式:https://<Keycloak域名>/realms/<你的Realm>/protocol/openid-connect/token/introspect)
    • 填入Keycloak中创建的用于WSO2校验的客户端ID和密钥,保存配置

二、Spring Boot端配置:双重令牌校验

需要配置两个SecurityFilterChain,分别处理WSO2应用令牌的有效性校验,以及Keycloak用户令牌的角色权限校验。

1. 依赖配置

确保pom.xml中包含Spring Security OAuth2 Resource Server依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>

2. Security配置类

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class DualAuthSecurityConfig {

    // 校验WSO2应用令牌:确保请求来自合法订阅的应用
    @Bean
    public SecurityFilterChain appTokenFilterChain(HttpSecurity http) throws Exception {
        http
            .securityMatcher("/api/**")
            .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
            .oauth2ResourceServer(oauth2 -> oauth2
                .jwt(jwt -> jwt
                    .issuerUri("https://<WSO2域名>/oauth2/token")
                    .jwtAuthenticationConverter(wso2JwtConverter())
                )
            );
        return http.build();
    }

    // 校验Keycloak用户令牌:验证用户角色权限
    @Bean
    public SecurityFilterChain userTokenFilterChain(HttpSecurity http) throws Exception {
        http
            .securityMatcher("/api/**")
            .authorizeHttpRequests(auth -> auth
                // 替换为你的API所需角色
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .requestMatchers("/api/user/**").hasRole("USER")
                .anyRequest().authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2
                .jwt(jwt -> jwt
                    .issuerUri("https://<Keycloak域名>/realms/<你的Realm>")
                    .jwkSetUri("https://<Keycloak域名>/realms/<你的Realm>/protocol/openid-connect/certs")
                    .jwtAuthenticationConverter(keycloakJwtConverter())
                )
            );
        return http.build();
    }

    // 自定义转换器:提取WSO2应用令牌中的权限(比如scope)
    private Converter<Jwt, AbstractAuthenticationToken> wso2JwtConverter() {
        return jwt -> {
            Collection<String> scopes = jwt.getClaimAsStringList("scope");
            Collection<GrantedAuthority> authorities = scopes.stream()
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());
            return new JwtAuthenticationToken(jwt, authorities);
        };
    }

    // 自定义转换器:处理Keycloak令牌中的角色(添加ROLE_前缀适配Spring Security)
    private Converter<Jwt, AbstractAuthenticationToken> keycloakJwtConverter() {
        return jwt -> {
            Map<String, Object> realmAccess = jwt.getClaim("realm_access");
            Collection<String> roles = (Collection<String>) realmAccess.get("roles");
            Collection<GrantedAuthority> authorities = roles.stream()
                .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
                .collect(Collectors.toList());
            return new JwtAuthenticationToken(jwt, authorities);
        };
    }
}

3. 配置文件(application.yml)

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          # WSO2和Keycloak的JWT配置已在代码中通过issuerUri指定,这里可留空或统一配置

三、前端请求方式

前端发起请求时,需要在请求头中同时携带两个令牌:

  • Authorization: Bearer <WSO2生成的应用订阅令牌>:用于WSO2校验应用订阅权限
  • X-User-JWT: Bearer <Keycloak颁发的用户身份令牌>:用于后端Spring Security校验用户角色

四、常见问题排查

  • 应用令牌校验失败:检查WSO2中应用是否订阅了目标API,应用令牌的scope是否包含API的权限范围
  • 用户角色校验失败:检查Keycloak中用户是否被分配了对应角色,Spring Security的角色前缀是否和Keycloak的角色匹配(比如Keycloak角色是admin,Spring Security需要ROLE_admin)
  • 令牌传递失败:检查WSO2的API头转发配置是否正确,后端是否能接收到X-User-JWT头

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 04:57:07