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

ASP.NET Core基于策略授权的UnauthorizedAccessException异常处理问题

设计原因
  1. ASP.NET Core 请求管道是按注册顺序执行的,你定义的ExceptionFilter属于MVC过滤器范畴,仅当请求进入MVC中间件处理流程后才会生效。而认证异常抛出在AuthenticationMiddleware(认证中间件)阶段,该中间件默认注册在MVC中间件之前,异常触发时请求还未进入MVC管道,因此过滤器无法捕获。
  2. 你遇到的IDW10201异常是Microsoft.Identity.Web库的默认校验逻辑抛出的:该库默认要求访问API的令牌必须携带scope或roles声明,校验不通过直接抛出未处理异常,未处理的管道异常默认会被转换为HTTP 500状态码。
解决方案

以下三个方案按推荐优先级排序:

方案1:关闭默认scope/roles校验,走自定义授权逻辑

这是最贴合你需求的方案,关闭库的默认校验后,请求会直接进入你定义的MyPolicy授权策略校验,校验不通过默认返回403状态码:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)     
    .AddMicrosoftIdentityWebApi(
        jwtOptions =>
        {
            Configuration.Bind("AAD", jwtOptions);
            // 关闭默认的scope/roles强制校验
            jwtOptions.AllowWebApiToBeAuthorizedByACL = true;
        }, 
        msIdentityOptions => Configuration.Bind("AAD", msIdentityOptions)
    );

方案2:自定义全局异常处理中间件

如果需要捕获所有管道阶段的异常做统一映射,可以在管道最开头注册自定义中间件:

第一步:实现中间件逻辑

public class AuthExceptionHandlerMiddleware
{
    private readonly RequestDelegate _next;

    public AuthExceptionHandlerMiddleware(RequestDelegate next) => _next = next;

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (UnauthorizedAccessException ex) when (ex.Message.Contains("IDW10201"))
        {
            context.Response.StatusCode = StatusCodes.Status403Forbidden;
            context.Response.ContentType = "application/json";
            await context.Response.WriteAsJsonAsync(new
            {
                Code = 403,
                Message = "令牌缺少必要的访问声明"
            });
        }
    }
}

第二步:注册中间件到管道最顶端

在Startup.cs的Configure方法中,将该中间件放在所有其他中间件之前:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // 第一个注册
    app.UseMiddleware<AuthExceptionHandlerMiddleware>();
    
    // 后面再注册其他中间件,如异常页、认证、授权、路由、MVC等
    // ...
}

方案3:定制JwtBearer认证事件

直接在认证组件的事件中处理异常,避免异常向上抛出:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)     
    .AddMicrosoftIdentityWebApi(
        jwtOptions =>
        {
            Configuration.Bind("AAD", jwtOptions);
            jwtOptions.Events = new JwtBearerEvents
            {
                OnAuthenticationFailed = context =>
                {
                    if (context.Exception is UnauthorizedAccessException && context.Exception.Message.Contains("IDW10201"))
                    {
                        context.Response.StatusCode = StatusCodes.Status403Forbidden;
                        context.ExceptionHandled = true;
                    }
                    return Task.CompletedTask;
                }
            };
        }, 
        msIdentityOptions => Configuration.Bind("AAD", msIdentityOptions)
    );

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 08:30:00