ASP.NET Core 6 Web API中AuthorizationHandler未触发问题求助
你的代码存在几个关键问题,导致ScreenAuthorizationHandler未被触发:
- 自定义的
ScreenAuthorizationAttribute只是普通Attribute,ASP.NET Core授权系统不会自动识别它作为授权规则的一部分。 - 控制器方法上的
[Authorize]未指定你定义的ScreenAuthorizationPolicy,授权系统不会执行对应的Requirement和Handler。 ScreenAuthorizationRequirement未携带ScreenID和PermissionLevel参数,Handler无法获取授权检查所需的业务信息。
以下是分步解决方案:
1. 修改自定义授权属性,关联到策略
将ScreenAuthorizationAttribute改为继承AuthorizeAttribute,并指定要使用的策略名称,让ASP.NET Core将其视为授权属性:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)] public class ScreenAuthorizationAttribute : AuthorizeAttribute { public Screens ScreenID { get; } public PermissionLevel PermissionLevel { get; } public ScreenAuthorizationAttribute(Screens screenID, PermissionLevel permissionLevel) { Policy = "ScreenAuthorizationPolicy"; ScreenID = screenID; PermissionLevel = permissionLevel; } }
2. 更新Requirement,添加业务参数
修改ScreenAuthorizationRequirement,添加用于接收属性参数的字段:
public class ScreenAuthorizationRequirement : IAuthorizationRequirement { public Screens ScreenID { get; } public PermissionLevel PermissionLevel { get; } public ScreenAuthorizationRequirement(Screens screenID, PermissionLevel permissionLevel) { ScreenID = screenID; PermissionLevel = permissionLevel; } }
3. 注册自定义策略提供程序
添加一个IAuthorizationPolicyProvider实现,动态根据属性参数生成授权策略:
public class ScreenAuthorizationPolicyProvider : DefaultAuthorizationPolicyProvider { private readonly IOptions<AuthorizationOptions> _options; public ScreenAuthorizationPolicyProvider(IOptions<AuthorizationOptions> options) : base(options) { _options = options; } public override async Task<AuthorizationPolicy?> GetPolicyAsync(string policyName) { var policy = await base.GetPolicyAsync(policyName); if (policy != null) return policy; if (policyName == "ScreenAuthorizationPolicy") { var policyBuilder = new AuthorizationPolicyBuilder(); policyBuilder.Requirements.Add(new ScreenAuthorizationRequirement(default, default)); return policyBuilder.Build(); } return null; } }
在Program.cs中注册该提供程序:
builder.Services.AddSingleton<IAuthorizationPolicyProvider, ScreenAuthorizationPolicyProvider>();
4. 修改AuthorizationHandler,获取属性参数并执行逻辑
更新ScreenAuthorizationHandler,从请求端点元数据中获取自定义属性的参数,执行授权检查:
public class ScreenAuthorizationHandler : AuthorizationHandler<ScreenAuthorizationRequirement> { private readonly IHttpContextAccessor _httpContextAccessor; public ScreenAuthorizationHandler(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } protected override Task HandleRequirementAsync( AuthorizationHandlerContext context, ScreenAuthorizationRequirement requirement) { var endpoint = _httpContextAccessor.HttpContext?.GetEndpoint(); var screenAuthAttribute = endpoint?.Metadata.GetMetadata<ScreenAuthorizationAttribute>(); if (screenAuthAttribute != null) { // 此处替换为你的自定义授权逻辑 var targetScreen = screenAuthAttribute.ScreenID; var requiredPermission = screenAuthAttribute.PermissionLevel; context.Succeed(requirement); } else { context.Fail(); } return Task.CompletedTask; } }
在Program.cs中注册IHttpContextAccessor:
builder.Services.AddHttpContextAccessor();
5. 更新控制器方法
直接使用自定义的[ScreenAuthorization]属性,它已继承AuthorizeAttribute,会同时触发AWS Cognito认证和自定义授权:
[Route("api/[controller]/Endpoint")] [ScreenAuthorization(Screens.screen1, PermissionLevel.Read)] public async Task<IActionResult> GetSomething() { // 业务逻辑代码 }
最后确认Program.cs的中间件顺序正确(已有代码符合要求):
app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.UseCors("*"); app.Run();
完成以上修改后,ScreenAuthorizationHandler会被正确触发,且能获取到指定的ScreenID和PermissionLevel参数执行自定义授权逻辑。
内容的提问来源于stack exchange,提问作者Yaron
相关产品推荐
相关产品推荐

