ASP.NET中的401.2的customerrors

时间:2010-01-13 13:47:00

标签: asp.net http-status-code-401 custom-errors

我在ASP.NET中成功实现了基于角色的授权。当一个人没有所需的角色时,他会看到401.2未经授权的错误页面。

我现在想要完成的是在我的应用程序中有一个自定义的401页面,并通过web.config中的设置将其重定向到那里。我试过这个:

<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
    <error statusCode="401" redirect="NoAccess.htm" />
</customErrors>

但这并没有被抓住。我是否必须在IIS中覆盖它?我希望不会因为这会使部署更加困难。

4 个答案:

答案 0 :(得分:7)

我最近遇到了同样的问题,结果发现这是使用Windows身份验证时的一个怪癖。

Joshua Flanagan不久前创建了一个nice HttpModule,它将尊重web.config中的customErrors部分并重定向到401错误页面。

  

解决方案的关键是拦截页面生命周期的 EndRequest 事件,检查401状态代码,然后执行自定义页面。

HttpModule的可移植性很好,因为它使解决方案可以重复使用,并保持你的Global.asax干净,但是如果你真的想要的话,没有什么能阻止你用他的代码在Global.asax中连接你的EndRequest事件。

如果您使用的是ASP.NET MVC,那么解决方案就不那么优雅了。

答案 1 :(得分:3)

如果您不想添加HttpModule

web.config中的

<system.web>
    <customErrors mode="On" defaultRedirect="~/MyController/MyErrorAction/" redirectMode="ResponseRedirect">
      <error statusCode="401" redirect="~/MyController/MyErrorAction/" />
    </customErrors>

在global.asax.cs

    protected void Application_EndRequest(object sender, EventArgs e)
    {
        HttpApplication application = (HttpApplication)sender;

        if (application.Response.StatusCode != 401 || !application.Request.IsAuthenticated) return;

        application.Response.ClearContent();

        //You can replace the piece below is to redirect using MVC, or your can replace all this with application.Server.Execute(yourPage);
        IController errorController = new SharedController();
        var rd = new RouteData();
        rd.Values.Add("controller", "MyController");
        rd.Values.Add("action", "MyErrorAction");
        rd.Values.Add("value", "You or your user group do not have permissions to use the address: " + Request.Url.PathAndQuery);

        errorController.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
        HttpContext.Current.Server.ClearError();
    }

答案 2 :(得分:3)

这是一个MVC无关的变体:

在Web.config中

<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
    <error statusCode="401" redirect="NoAccess.htm" />
</customErrors>

在Global.asax.cs

protected void Application_EndRequest(object sender, EventArgs e)
{
    HttpApplication application = (HttpApplication)sender;

    if (application.Response.StatusCode != 401 || !application.Request.IsAuthenticated) return;

    var customErrors = (CustomErrorsSection)ConfigurationManager.GetSection("system.web/customErrors");

    var accessDeniedPath = customErrors.Errors["401"] != null ? customErrors.Errors["401"].Redirect : customErrors.DefaultRedirect;
    if (string.IsNullOrEmpty(accessDeniedPath))
        return; // Let other code handle it (probably IIS).

    application.Response.ClearContent();
    application.Server.Execute(accessDeniedPath);
    HttpContext.Current.Server.ClearError();
}

答案 3 :(得分:1)

这对我来说效果很好。

Global.asax -

    protected void Application_EndRequest(object sender, EventArgs e)
    {
        if (Response.StatusCode == 401 && Request.IsAuthenticated)
        {
            Response.StatusCode = 303;
            Response.Clear();
            Response.Redirect("~/AccessDenied.html");
            Response.End();
        }
    }

Web.config -

  <system.web>
    <customErrors mode="On">
      <error statusCode="401" redirect="AccessDenied.html"/>
    </customErrors>
    <authentication mode="Windows"/>
  </system.web>
  <location path="AccessDenied.html">
    <system.web>
      <authorization>
        <allow roles="*"/>
      </authorization>
    </system.web>
  </location>
  <location path=".">
    <system.web>
      <authorization>
        <allow roles="YourADGroup"/>
        <deny users="*" />
      </authorization>
    </system.web>
  </location>

这也会在200期之前处理双401。 还可以绕过讨厌的firefox身份验证弹出窗口。