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

.NET Core未授权访问自定义错误处理问题排查与优化

解决方案

1. 直接访问Error/Error时无异常信息的问题

直接访问/Error/Error时,并没有触发任何异常,所以HttpContext.Features.Get<IExceptionHandlerFeature>()自然返回null,这是正常行为。你可以在Error方法里做场景区分:

  • 异常触发的错误跳转:此时存在IExceptionHandlerFeature,可获取异常详情
  • 手动访问错误页面:此时无异常信息,返回通用提示即可

示例代码:

public IActionResult Error()
{
    var exceptionFeature = HttpContext.Features.Get<IExceptionHandlerFeature>();
    var errorViewModel = new ErrorViewModel();

    if (exceptionFeature != null)
    {
        errorViewModel.ExceptionMessage = exceptionFeature.Error.Message;
        errorViewModel.StackTrace = exceptionFeature.Error.StackTrace;
        // 记录异常日志
        _logger.LogError(exceptionFeature.Error, "未处理异常");
    }
    else
    {
        // 手动访问场景的提示
        errorViewModel.ExceptionMessage = "未检测到异常,这是直接访问的错误页面";
    }

    return View(errorViewModel);
}

2. 获取403/404等状态码错误的更多信息

要获取状态码错误的额外信息,需正确配置中间件,并利用ASP.NET Core提供的扩展Feature:

步骤1:配置中间件(Program.cs/Startup.cs)

确保中间件顺序正确,UseExceptionHandler和UseStatusCodePagesWithReExecute要放在UseRouting、UseAuthorization之前:

// .NET 6+ 顶级语句示例
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

var app = builder.Build();

// 异常捕获跳转
app.UseExceptionHandler("/Error/Error");
// 捕获状态码错误并转发到Error控制器
app.UseStatusCodePagesWithReExecute("/Error/Error", "?statusCode={0}");

app.UseRouting();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

步骤2:在ErrorController中获取更多信息

除状态码外,还可通过以下Feature获取额外数据:

  • IStatusCodeReExecuteFeature:获取原始请求的路径、查询字符串
  • IAuthorizationFailureFeature:获取403授权失败的详细原因(如未满足的策略、权限要求)

示例代码:

public IActionResult Error(int? statusCode)
{
    var errorViewModel = new ErrorViewModel
    {
        StatusCode = statusCode ?? HttpContext.Response.StatusCode
    };

    // 获取原始请求信息
    var reExecuteFeature = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
    if (reExecuteFeature != null)
    {
        errorViewModel.OriginalPath = reExecuteFeature.OriginalPath;
        errorViewModel.OriginalQueryString = reExecuteFeature.OriginalQueryString;
    }

    // 获取403授权失败详情
    if (errorViewModel.StatusCode == 403)
    {
        var authFailureFeature = HttpContext.Features.Get<IAuthorizationFailureFeature>();
        if (authFailureFeature != null)
        {
            errorViewModel.AuthFailureReasons = authFailureFeature.Failure.FailedRequirements
                .Select(r => r.GetType().Name)
                .ToList();
        }
    }

    // 获取异常信息(如果是异常触发的状态码错误)
    var exceptionFeature = HttpContext.Features.Get<IExceptionHandlerFeature>();
    if (exceptionFeature != null)
    {
        errorViewModel.ExceptionMessage = exceptionFeature.Error.Message;
        _logger.LogError(exceptionFeature.Error, "异常触发状态码 {StatusCode}", errorViewModel.StatusCode);
    }
    else
    {
        _logger.LogWarning("状态码错误 {StatusCode},原始路径:{OriginalPath}", 
            errorViewModel.StatusCode, errorViewModel.OriginalPath);
    }

    return View(errorViewModel);
}

步骤3:ErrorViewModel示例

定义视图模型承载信息:

public class ErrorViewModel
{
    public int StatusCode { get; set; }
    public string? ExceptionMessage { get; set; }
    public string? StackTrace { get; set; }
    public string? OriginalPath { get; set; }
    public string? OriginalQueryString { get; set; }
    public List<string>? AuthFailureReasons { get; set; }
}

3. 日志记录注意事项

  • 注入ILogger<ErrorController>到控制器,日志需包含状态码、原始请求、异常栈等上下文信息
  • 404错误记录原始路径,方便排查无效链接
  • 403错误记录授权失败原因,辅助调整权限策略

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:28:11