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

使用Keycloak作为授权服务器时资源服务器报错:enc(use)暂不支持

解决Spring Security资源服务器"enc (use) is currently not supported"错误

问题根源

Keycloak 15返回的JWK(JSON Web Key)集合中包含了**加密用途(use=enc)的密钥,但你当前使用的JwkTokenStore属于Spring Security OAuth2的旧实现,仅支持处理签名验证用途(use=sig)**的密钥,加载JWK时触发不支持的错误,导致请求在过滤器阶段就失败,无法进入控制器。

解决方案

推荐切换到Spring Security 5.x引入的OAuth2资源服务器新API(旧的@EnableResourceServer已进入维护模式),新API会自动处理不同用途的JWK,同时更适配现代OAuth2/JWT场景。

步骤1:替换资源服务器配置类

删除原有的ResourceServerConfig,改用以下基于SecurityFilterChain的配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig {

    @Value("${claim.aud}")
    private String claimAud;

    @Value("${jwkSetUri}")
    private String urlJwk;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .mvcMatchers(HttpMethod.DELETE, "/**").hasAuthority("fitnessadmin")
                .anyRequest().authenticated()
                .and()
                .oauth2ResourceServer(oauth2 -> oauth2
                        .jwt(jwt -> jwt
                                .jwkSetUri(urlJwk)
                                // 验证token的audience是否匹配资源ID
                                .audienceValidator(audience -> audience.contains(claimAud))
                                // 自定义JWT到权限的转换(适配Keycloak的roles声明)
                                .jwtAuthenticationConverter(jwtAuthenticationConverter())
                        )
                );
        return http.build();
    }

    @Bean
    public JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtGrantedAuthoritiesConverter authoritiesConverter = new JwtGrantedAuthoritiesConverter();
        // 指定Keycloak中存储角色的声明字段
        authoritiesConverter.setAuthoritiesClaimName("roles");
        // 去掉默认的"SCOPE_"前缀,因为你的角色是fitnessuser、fitnessadmin
        authoritiesConverter.setAuthorityPrefix("");

        JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
        converter.setJwtGrantedAuthoritiesConverter(authoritiesConverter);
        return converter;
    }
}

步骤2:确保依赖正确

如果你的项目使用Maven,确保引入了Spring Security OAuth2资源服务器的starter:

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

备选方案(兼容旧API)

如果暂时不想切换新API,可以自定义JWK过滤逻辑,只加载use=sig的密钥:

@Bean
public TokenStore tokenStore() {
    JwkSetUriJwtAccessTokenConverter converter = new JwkSetUriJwtAccessTokenConverter();
    converter.setJwkSetUri(urlJwk);
    // 自定义JWK转换器,过滤加密密钥
    converter.setJwkConverter(jwkSet -> {
        List<JWK> filteredJwks = jwkSet.getKeys().stream()
                .filter(jwk -> "sig".equals(jwk.getUse()))
                .collect(Collectors.toList());
        return new JWKSet(filteredJwks);
    });
    return new JwtTokenStore(converter);
}

验证修改

  1. 重启资源服务器
  2. 使用已获取的access token请求添加健身记录的接口
  3. 此时过滤器会正常处理JWT验证,请求能进入控制器,断点可以触发

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 20:48:14