ASP.NET MVC 应用程序的自定义 401 错误页面

Custom 401 error page for ASP.NET MVC application

我创建了一个使用集成 Windows 身份验证的 ASP.NET MVC 应用程序。实施了以下授权逻辑:

  1. 尝试通过 NTLM 从活动目录中获取帐户凭据。

    • 如果收到凭据并且 Windows 帐户具有所需的权限,则执行请求的操作。
    • 否则转到第 2 条。
  2. 显示 Windows 身份验证对话框,以便用户可以提供其他凭据:

    • 如果收到另一个凭据并且用户具有所需的权限,则执行请求的操作。
    • 如果未收到其他凭据或帐户权限低于要求,则重复第 2 条。
    • 如果身份验证对话框被取消,则显示 401 错误消息。

然后我为应用程序添加了自定义错误页面,使用 VictorySaber's solution:

protected void Application_EndRequest()
{
    int status = Response.StatusCode;
    string actionName;
    if (status >= 400 && status < 500)
    {
        switch (status)
        {
            case 401:
                actionName = "Unauthorized";
                break;

            // Handle another client errors

            default:
                actionName = "BadRequest";
                break;
            }
        }
    else if (status >= 500 && status < 600)
    {
        switch (status)
        {
            case 501:
                actionName  = "NotImplemented";
                break;

            // Handle another server errors

            default:
                actionName  = "InternalServerError";
                break;
        }
    }
    if (!String.IsNullOrEmpty(actionName))
    {
        Response.Clear();
        var rd = new RouteData();
        rd.Values["controller"] = "Errors";
        rd.Values["action"] = actionName;
        IController c = new ErrorsController();
        c.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
    }
}

因此,我的友好错误页面被呈现。但是 Windows 身份验证对话框不会出现。如果出现 401 HTTP 状态代码,它会立即显示 401 错误消息。 web.config 文件的 <httpErrors> 部分的技巧给出了相同的结果。

此外,我发现 proposal 可以捕获 401.2 HTTP 状态代码,该代码应该在取消对话框时出现。但在我的情况下,代码永远不会出现。

如何使用用户友好的错误页面而不是默认消息而不更改身份验证对话框逻辑?

我需要实现以下要求:

  1. Windows 身份验证对话框仅针对其 AD 帐户没有所需权限的用户出现,以允许用户提供其他凭据。
  2. 未提供正确的凭据或用户未取消时出现该对话框。
  3. 只有在用户取消对话框时才会显示自定义 401 错误页面。

默认情况下,只有设置了 SetStatus 标志,服务器才会保持响应不变。因此,有必要明确指定当 HTTP 状态代码为错误时 IIS 必须对现有响应执行的操作。

一种方法是配置 Web.config 文件中 <system.webServer> 部分的 <httpErrors> 元素。只需将 existingResponse 属性值设置为 PassThrough,以便服务器在现有响应存在时保持响应不变。

<system.webServer>

  <!-- configuration settings -->

  <httpErrors errorMode="Custom" existingResponse="PassThrough" />
</system.webServer>

如果服务器提示输入 Windows 用户帐户凭据,配置会阻止错误页面呈现。这 response 将在对话框取消后替换为错误页面。

通过 HttpResponseTrySkipIisCustomErrors 属性 禁用 IIS 自定义错误可以实现相同的结果。所以 在问题的代码中添加以下行可以解决问题:

Context.Response.TrySkipIisCustomErrors = true;

由于某种原因,第二种方法在我的生产服务器上不起作用。我认为,它需要额外的服务器设置。