Hot Chocolate(ChiliCream) 是否可按请求配置不同QueryType
Hot Chocolate 按请求区分QueryType实现方案
默认情况下Hot Chocolate的QueryType会在服务启动阶段完成构建,生成静态Schema单例,官方默认配置示例如下:
public class Startup { public void ConfigureServices(IServiceCollection services) { services .AddGraphQLServer() .AddQueryType<QueryType>(); // here } }
可以实现按单个请求的API Key区分返回不同的Query访问能力,主流实现方案有两种:
方案1:多Schema绑定独立路由,按API Key分发
- 为不同权限等级的客户端分别定义独立的QueryType,启动时注册多个GraphQL服务,每个服务绑定对应QueryType
- 网关层提取请求头的API Key,校验权限后转发到对应权限级别的GraphQL端点即可
配置示例:
public class Startup { public void ConfigureServices(IServiceCollection services) { // 注册普通用户权限Schema services .AddGraphQLServer("CommonSchema") .AddQueryType<CommonQuery>(); // 注册管理员权限Schema services .AddGraphQLServer("AdminSchema") .AddQueryType<AdminQuery>(); } public void Configure(IApplicationBuilder app) { app.UseRouting(); app.UseEndpoints(endpoints => { // 不同权限Schema绑定独立路由 endpoints.MapGraphQL("/graphql/common", schemaName: "CommonSchema"); endpoints.MapGraphQL("/graphql/admin", schemaName: "AdminSchema"); }); } }
该方案适合不同权限等级的Query结构差异较大的场景,Schema隔离性强,运行时性能更高。
方案2:单Schema+请求级字段权限过滤
如果不想维护多套Schema,也可以在单静态QueryType中定义所有可用字段,请求阶段根据API Key对应的权限过滤无权限访问的字段,效果上等同于不同请求拿到的QueryType不同:
- 自定义权限校验逻辑,从请求头提取API Key匹配对应权限等级
- 给不同Query字段绑定对应权限要求,无权限的字段会自动从返回的Schema中隐藏
配置示例:
// 自定义API Key权限校验逻辑 public class ApiKeyPermissionHandler : AuthorizationHandler<ApiKeyRequirement> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ApiKeyRequirement requirement) { if (context.Resource is IHttpContextAccessor accessor) { var apiKey = accessor.HttpContext.Request.Headers["X-API-Key"].FirstOrDefault(); // 校验API Key对应权限是否满足要求 if (ValidateApiKeyPermission(apiKey, requirement.RequiredPermission)) { context.Succeed(requirement); } } return Task.CompletedTask; } } // Query定义,给不同字段指定权限要求 public class Query { [Authorize(Policy = "CommonUser")] public string GetPublicData() => "公共数据"; [Authorize(Policy = "AdminUser")] public string GetSensitiveData() => "敏感数据"; } // 服务注册配置 public class Startup { public void ConfigureServices(IServiceCollection services) { // 注册权限策略 services.AddAuthorization(options => { options.AddPolicy("CommonUser", policy => policy.AddRequirements(new ApiKeyRequirement(PermissionLevel.Common))); options.AddPolicy("AdminUser", policy => policy.AddRequirements(new ApiKeyRequirement(PermissionLevel.Admin))); }); services.AddHttpContextAccessor(); services.AddSingleton<IAuthorizationHandler, ApiKeyPermissionHandler>(); services .AddGraphQLServer() .AddAuthorization() .AddQueryType<Query>(); } }
该方案适合不同权限的Query结构差异较小、仅部分字段需要权限控制的场景,维护成本更低。
内容的提问来源于stack exchange,提问作者Júlio Almeida
相关产品推荐
相关产品推荐

