简体   繁体   English

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

[英]Custom 401 error page for ASP.NET MVC application

I created an ASP.NET MVC application that uses integrated Windows Authentication.我创建了一个使用集成 Windows 身份验证的 ASP.NET MVC 应用程序。 The following authorization logic was implemented:实现了以下授权逻辑:

  1. Try to get account credentials from active directory through NTLM.尝试通过 NTLM 从活动目录获取帐户凭据。

    • If credentials are received and the Windows account has required permissions then perform requested action.如果收到凭据并且 Windows 帐户具有所需的权限,则执行请求的操作。
    • In otherwise go to clause 2.否则转到第 2 条。
  2. Display the Windows authentication dialog, so a user can provide another credentials:显示 Windows 身份验证对话框,以便用户可以提供另一个凭据: 身份验证对话框

    • If another credentials are received and the user has required permissions then perform requested action.如果收到另一个凭据并且用户具有所需的权限,则执行请求的操作。
    • If another credentials are not received or the account permissions are less then it requires, then repeat clause 2.如果未收到其他凭据或帐户权限低于要求,则重复第 2 条。
    • If authentication dialog is cancelled then display 401 error message.如果身份验证对话框被取消,则显示 401 错误消息。

Then I have added custom error pages for the application, using VictorySaber's solution :然后我使用VictorySaber 的解决方案为应用程序添加了自定义错误页面:

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));
    }
}

As result my friendly error pages are rendered.结果我的友好错误页面被呈现。 But the Windows authentication dialog does not appear.但不会出现 Windows 身份验证对话框。 If the 401 HTTP status code occurs it immediately displays 401 error message.如果出现 401 HTTP 状态代码,它会立即显示 401 错误消息。 The trick with the <httpErrors> section of web.config file gives same result. web.config文件的<httpErrors>部分的技巧给出了相同的结果。

Also, I found proposal to catch the 401.2 HTTP status code that should occur when the dialog is cancelled.另外,我发现了捕获取消对话框时应该发生的401.2 HTTP 状态代码的建议 But in my case the code never occurs.但在我的情况下,代码永远不会发生。

How to use user friendly error pages instead of default messages but don't change authentication dialog logic?如何使用用户友好的错误页面而不是默认消息但不更改身份验证对话框逻辑?

I need to implement the following requirements:我需要实现以下要求:

  1. The Windows authentication dialog is appeared only for a user, whose AD account doesn't have required permissions, to allow the user provides another credentials. Windows 身份验证对话框仅针对其 AD 帐户没有所需权限的用户显示,以允许用户提供另一个凭据。
  2. The dialog is appeared while correct credentials are not provided or user doesn't cancel it.当没有提供正确的凭据或用户没有取消它时,会出现该对话框。
  3. The custom 401 error page will be displayed only if the user cancels the dialog.只有当用户取消对话框时才会显示自定义 401 错误页面。

By default the server leaves the response untouched only if the SetStatus flag is set.默认情况下,仅当设置了SetStatus标志时,服务器才会保持响应不变。 So, it is necessary to clearly specifiy what IIS must to do with an existing response when the HTTP status code is an error.因此,有必要明确指定当 HTTP 状态代码为错误时 IIS 必须对现有响应做什么。

One way is to configure the <httpErrors> element of <system.webServer> section in the Web.config file.一种方法是在Web.config文件中配置<system.webServer>部分的<httpErrors>元素。 Just set existingResponse attribute value to PassThrough , so that the server leaves the response untouched if an existing response exists.只需将existingResponse属性值设置为PassThrough ,以便服务器在现有响应存在时保持响应不变。

<system.webServer>

  <!-- configuration settings -->

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

The configuration prevent error page rendering if the sever prompts for a Windows user account credentials.如果服务器提示输入 Windows 用户帐户凭据,则该配置会阻止错误页面呈现。 The response will be replaced with the error page after the dialog cancellation.对话框取消后,响应将替换为错误页面。

The same result could be achieved by disabling of IIS custom errors through TrySkipIisCustomErrors property of HttpResponse .通过HttpResponse TrySkipIisCustomErrors属性禁用 IIS 自定义错误可以实现相同的结果。 So the addition the following line to code from the question solves the problem:因此,在问题代码中添加以下行可以解决问题:

Context.Response.TrySkipIisCustomErrors = true;

Note .注意 The second way does not work on my production server for some reason.由于某种原因,第二种方法在我的生产服务器上不起作用。 I think, it requires additional server settings.我认为,它需要额外的服务器设置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM