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

为带[Authorize]属性的ASP.NET Core接口返回自定义异常方法

自定义ASP.NET Core授权失败的401响应体

要给未授权访问返回带内容的自定义响应,你可以用以下几种方式实现:

方法1:JWT认证场景下配置挑战事件

如果你的项目基于JWT认证,直接在AddJwtBearer的配置中添加OnChallenge事件,覆盖默认的空响应:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
        };

        // 自定义未授权响应
        options.Events = new JwtBearerEvents
        {
            OnChallenge = async context =>
            {
                // 跳过默认的响应处理逻辑
                context.HandleResponse();
                
                // 构造自定义响应内容
                var errorResponse = new
                {
                    StatusCode = StatusCodes.Status401Unauthorized,
                    Message = "未授权访问,请提供有效的认证令牌",
                    Detail = "请求缺少合法的Authorization头或令牌已失效"
                };
                
                // 设置响应类型和状态码
                context.Response.ContentType = "application/json";
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                
                // 写入响应体
                await context.Response.WriteAsync(JsonSerializer.Serialize(errorResponse));
            }
        };
    });

方法2:自定义授权过滤器

如果需要更灵活的授权逻辑,或者不依赖JWT,可以自定义一个授权过滤器:

public class CustomAuthorizeFilter : IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        // 判断用户是否未通过认证
        if (!context.HttpContext.User.Identity.IsAuthenticated)
        {
            var customResponse = new
            {
                Code = 401,
                Message = "您没有权限访问此接口,请先完成认证",
                Timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss")
            };
            
            // 返回自定义JSON响应
            context.Result = new JsonResult(customResponse)
            {
                StatusCode = StatusCodes.Status401Unauthorized
            };
        }
    }
}

注册过滤器

  • 控制器级别:在目标控制器或接口上添加过滤器特性
[ApiController]
[Route("[controller]")]
[TypeFilter(typeof(CustomAuthorizeFilter))]
public class WeatherForecastController : ControllerBase
{
    // ... 控制器代码
}
  • 全局级别:在Program.cs中注册,对所有接口生效
builder.Services.AddControllers(options =>
{
    options.Filters.Add<CustomAuthorizeFilter>();
});

方法3:用中间件全局拦截401响应

这种方式可以统一处理所有返回401且响应体为空的情况,无需修改控制器或认证配置:

public class CustomUnauthorizedMiddleware
{
    private readonly RequestDelegate _next;

    public CustomUnauthorizedMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        // 先执行后续中间件
        await _next(context);

        // 检查是否是401且响应体为空
        if (context.Response.StatusCode == StatusCodes.Status401Unauthorized 
            && context.Response.ContentLength == 0)
        {
            context.Response.ContentType = "application/json";
            var errorResponse = new
            {
                Status = "error",
                Message = "未授权访问",
                StatusCode = 401
            };
            await context.Response.WriteAsync(JsonSerializer.Serialize(errorResponse));
        }
    }
}

注册中间件

在Program.cs中,将中间件放在UseAuthentication和UseAuthorization之后:

app.UseAuthentication();
app.UseAuthorization();

// 添加自定义未授权中间件
app.UseMiddleware<CustomUnauthorizedMiddleware>();

app.MapControllers();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 12:02:43