ASP.NET 中 401.2 的自定义错误
Posted
技术标签:
【中文标题】ASP.NET 中 401.2 的自定义错误【英文标题】:customerrors for 401.2 in ASP.NET 【发布时间】:2011-01-04 15:32:59 【问题描述】:我在 ASP.NET 中成功实现了基于角色的授权。当一个人没有所需的角色时,他会看到 401.2 未授权的错误页面。
我现在想要完成的是在我的应用程序中拥有一个自定义 401 页面,并通过 web.config 中的设置将其重定向到那里。我试过这个:
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="401" redirect="NoAccess.htm" />
</customErrors>
但这并没有被抓住。我是否必须在 IIS 中覆盖它?我希望这不会使部署变得更加困难。
【问题讨论】:
【参考方案1】:我最近遇到了同样的问题,事实证明这是使用 Windows 身份验证时的怪癖之一。
Joshua Flanagan 不久前创建了一个 nice HttpModule,它将尊重 web.config 中的 customErrors 部分并重定向到 401 错误页面。
解决的关键是拦截页面生命周期的EndRequest事件,检查401状态码,然后执行你的自定义页面。
HttpModule 的可移植性很好,因为它使解决方案可重用,并使您的 Global.asax 保持干净,但如果您真的想的话,没有什么能阻止您使用他的代码在 Global.asax 中连接 EndRequest 事件。
如果您使用的是 ASP.NET MVC,则该解决方案就没有那么优雅了。
【讨论】:
【参考方案2】:如果您不想添加 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();
【讨论】:
IsAuthenticated 的否定真的正确吗?不应该反过来吗,即如果经过身份验证 => 从方法返回? 如果页面上有会话变量,此方法似乎不起作用。当它尝试执行页面Object reference not set to an instance of an object
时我得到了这个【参考方案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();
【讨论】:
【参考方案4】:这对我来说很有效。
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 身份验证弹出窗口。
【讨论】:
以上是关于ASP.NET 中 401.2 的自定义错误的主要内容,如果未能解决你的问题,请参考以下文章