如何在ASP.NET层为类库中的EF Core实体添加HotChocolate授权特性
解决方案:在ASP.NET层为EF Core模型添加HotChocolate授权
方案1:使用HotChocolate类型扩展(推荐)
这是最贴合HotChocolate设计理念的方案,完全不需要在EF类库中引入HotChocolate依赖。你可以在ASP.NET项目中创建类型扩展类,为EF模型补加授权规则:
using HotChocolate.Authorization; using YourClassLibrary.Models; // 引用EF模型所在的类库 public class OrganisationTypeExtension : ObjectTypeExtension<Organisation> { protected override void Configure(IObjectTypeDescriptor<Organisation> descriptor) { // 为整个实体类添加授权策略 descriptor.Authorize("some-policy-name"); // 若需单独为某个字段设置授权,可单独配置 descriptor.Field(o => o.Name) .Authorize("another-policy"); } }
随后在Program.cs中注册这个扩展:
builder.Services.AddGraphQLServer() .AddQueryType(q => q.Name("Query")) .AddTypeExtension<OrganisationTypeExtension>() // 注册类型扩展 .AddAuthorization();
方案2:自定义元数据+授权拦截器
如果需要更灵活的跨层授权标记,可以先在EF类库中用自定义特性标记需要授权的类型/字段,再在ASP.NET层通过拦截器读取元数据并应用授权规则:
- 在EF类库中定义自定义标记特性:
// EF类库内代码,无HotChocolate依赖 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property)] public class RequirePolicyAttribute : Attribute { public string PolicyName { get; } public RequirePolicyAttribute(string policyName) { PolicyName = policyName; } } // 用自定义特性标记EF模型 [RequirePolicy("some-policy-name")] public class Organisation { public int Id { get; set; } [RequirePolicy("another-policy")] public string Name { get; set; } = null!; }
- 在ASP.NET项目中创建授权拦截器:
using HotChocolate.Authorization; using HotChocolate.Types; using System.Reflection; using YourClassLibrary.Models; using YourClassLibrary.Attributes; public class CustomAuthorizationInterceptor : IAuthorizationInterceptor { public void OnBeforeAuthorization(AuthorizationContext context) { // 处理类型级授权 if (context.Type is ObjectType objectType) { var policyAttr = objectType.RuntimeType.GetCustomAttribute<RequirePolicyAttribute>(); if (policyAttr != null) { context.RequirePolicy(policyAttr.PolicyName); } } // 处理字段级授权 if (context.Field is IObjectField field) { var property = field.Member as PropertyInfo; if (property != null) { var policyAttr = property.GetCustomAttribute<RequirePolicyAttribute>(); if (policyAttr != null) { context.RequirePolicy(policyAttr.PolicyName); } } } } public void AfterAuthorization(AuthorizationContext context) { // 无额外逻辑可留空 } }
- 在
Program.cs中注册拦截器:
builder.Services.AddGraphQLServer() .AddQueryType(q => q.Name("Query")) .AddAuthorization(options => { options.Interceptors.Add<CustomAuthorizationInterceptor>(); }) .AddType<Organisation>();
方案3:手动映射GraphQL类型(不推荐)
你也可以在ASP.NET项目中手动创建对应EF模型的GraphQL类型,并在映射时直接添加授权特性,但这种方式需要手动维护字段映射,后续模型变更时容易遗漏:
using HotChocolate.Authorization; using YourClassLibrary.Models; public class OrganisationType : ObjectType<Organisation> { protected override void Configure(IObjectTypeDescriptor<Organisation> descriptor) { descriptor.Authorize("some-policy-name"); descriptor.Field(o => o.Id).Type<IntType>(); descriptor.Field(o => o.Name).Type<StringType>().Authorize("another-policy"); } }
注册这个类型:
builder.Services.AddGraphQLServer() .AddQueryType(q => q.Name("Query")) .AddType<OrganisationType>() .AddAuthorization();
内容的提问来源于stack exchange,提问作者baouss
相关产品推荐
相关产品推荐

