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

Quarkus OIDC多租户:如何从gRPC调用元数据提取TenantId?

从gRPC元数据提取tenantId实现多租户OIDC配置

要在gRPC服务调用场景下复用相同的多租户策略,核心是从gRPC请求上下文中提取元数据,而非HTTP请求头。Quarkus的OIDC扩展在处理gRPC请求时,OidcRequestContext会实际是GrpcRequestContext类型,可通过它获取gRPC元数据。

修改后的实现代码

@ApplicationScoped
public class PartitionTenantResolver implements TenantConfigResolver {

    // 定义gRPC元数据键,gRPC默认会将键转为小写,建议统一用小写格式
    private static final Metadata.Key<String> DATA_PARTITION_ID_KEY = 
            Metadata.Key.of("data-partition-id", Metadata.ASCII_STRING_MARSHALLER);

    @Override
    public Uni<OidcTenantConfig> resolve(RoutingContext routingContext, OidcRequestContext<OidcTenantConfig> requestContext) {
        String dataPartitionId = null;

        // 处理gRPC请求场景
        if (requestContext instanceof GrpcRequestContext grpcContext) {
            Metadata metadata = grpcContext.getMetadata();
            dataPartitionId = metadata.get(DATA_PARTITION_ID_KEY);
        } 
        // 保留原有HTTP请求场景的处理逻辑,兼容两种请求类型
        else if (routingContext != null) {
            dataPartitionId = routingContext.request().getHeader("DATA_PARTITION_ID");
        }

        String keycloakUrl = ConfigProvider.getConfig().getValue("openid.provider.base-url", String.class);
        String clientId = ConfigProvider.getConfig().getValue("openid.provider.client-id", String.class);
        String secret = ConfigProvider.getConfig().getValue("openid.provider.secret", String.class);

        if (StringUtils.isNotEmpty(dataPartitionId)) {
            OidcTenantConfig config = new OidcTenantConfig();
            config.setAuthServerUrl(keycloakUrl + "/realms/" + dataPartitionId);
            config.setTenantId(dataPartitionId);
            config.setClientId(clientId);
            config.getCredentials().setSecret(secret);
            config.setApplicationType(OidcTenantConfig.ApplicationType.SERVICE);

            return Uni.createFrom().item(config);
        }
        return Uni.createFrom().nullItem();
    }
}

关键说明

  • 上下文类型判断:通过instanceof检查requestContext是否为GrpcRequestContext,以此区分gRPC和HTTP请求场景
  • gRPC元数据提取:使用Metadata.Key定义元数据键,遵循gRPC协议要求(键默认转为小写),避免大小写不匹配问题
  • 多场景兼容:保留原有HTTP请求头的处理逻辑,让同一个Resolver同时支持HTTP和gRPC两种请求类型

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 12:55:54