ASP.NET WindowsAuthentication自定义401未经授权错误页面

15

我有一个使用ActiveDirectory进行身份验证的ASP.NET网站。

现在,当已认证的用户打开页面时-他会自动被认证。我遇到了一个问题-当未经身份验证的用户(例如,没有定义network.automatic-ntlm-auth.trusted-uris属性的Mozilla Firefox用户)打开页面时,IIS发送401响应并提示登录\密码。

我希望的是不要提示他输入登录\密码-只显示自定义错误页面,这听起来很简单-认证用户获取所请求的页面,未认证用户被重定向到自定义错误页面。如果使用FormsAuthentication,它应该可以正常工作。

但是,我已经尝试了许多方法,任何Web.config重定向都无效。即使我清除了Response并把重定向放在那里-我也会得到一个循环,因为此自定义页面(*例如/Error/AccessDenied)也需要身份验证。将控制器标记为AllowAnonymous什么也没做。

但是,如果在IIS Manager中启用匿名身份验证,则真实认证的域用户在打开网站时不会被授权。

我该如何解决这个问题?


您希望非IE用户被重定向到另一个页面吗?基于用户代理的URL重写是可行的方法。 - Lex Li
不可能。浏览器的第一个请求总是匿名的。IIS 始终会响应 401 未授权,并带有 www.authenticate: negotiate(或 NTLM 或两者)头信息。然后客户端(浏览器)再次请求,这次带有 Authorization: Negotiate ..hash.. 头信息。根据受信任站点的不同,浏览器始终要求凭据。您无法显示自定义错误,因为第一次响应始终是 401,无论如何。 - Abhitalks
你可以编写一个HTTP模块并挂钩HttpApplication.PostAuthenticateRequest。从那里,你可以使用HttpContext.RewritePath和/或几乎以任何你想要的方式操作响应上下文。如果没有明确的重现案例,很难再多说了。 - Simon Mourier
@Abhitalks 由于您的回答帮助了我最多,我想为它提供一个奖励。您能否将其作为答案发布? - Yeldar Kurmangaliyev
1
@YeldarKurmangaliyev:不用担心赏金的问题。解决你的问题更重要。请接受你的答案。它写得很好,能够清晰地传达重要部分。或者,你可以等待赏金期结束,说不定会有更好的答案出现。 :) - Abhitalks
@Abhitalks,我能否在我的应用程序布局页面中获取所有系统生成的错误?我不想为不同的错误使用自定义页面。我只想原样显示系统生成的消息,但是在我的_layout.cshtml页面中显示。谢谢。 - ary
3个回答

23

感谢@Abhitalks在评论中解释它的工作原理。我不知道为什么,但我确信IE和Google Chrome会在第一次请求时发送授权头,这就是为什么只有未经授权的用户会收到401响应的原因。在我理解到根本无法避免401响应之后,我决定使用这种简单的方法,因为这种行为最接近期望的行为。

我在Global.asax中添加了以下方法:

protected void Application_EndRequest(object sender, EventArgs e)
{
    if (Response.StatusCode == 401)
    {
        Response.ClearContent();
        Response.WriteFile("~/Static/NotAuthorized.html");
        Response.ContentType = "text/html";
    }
}

现在,当用户打开一个页面时,服务器会返回一个带有401 Unauthorized头的自定义错误页面。

Chrome,IE或配置良好的Firefox。用户请求URL,服务器返回带有401标头的错误页面 - 浏览器自动完成授权挑战,重定向到相同的URL,服务器现在返回正确的页面和200请求成功代码。用户将看不到此错误页面。

未配置的Firefox。用户请求URL,服务器返回带有401标头的错误页面 - 浏览器无法完成授权挑战并提示用户输入凭据。

  • 用户输入正确的登录信息。用户再次请求相同的URL,获得页面和200 OK。

  • 用户输入错误的登录信息。浏览器再次提示输入凭据。

  • 用户按下取消按钮。浏览器显示发送带有401头的自定义错误页面。此页面告诉用户,如果使用Firefox,则应输入凭据或允许自动NTLM身份验证。


谢谢,我一直在寻找这个。给你点赞。 - KoenW

3

关于Yeldar评论的重要补充:

当更改远程请求(即非本地主机)的响应消息时,您需要将以下内容添加到配置文件中:

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

如果您不允许响应"通过"远程客户端,那么这些客户端将会得到默认的 "You do not have permission to view this directory or page" 信息。
我从这里获取了这个信息:https://dev59.com/O2855IYBdhLWcg3waDiR#17324195

0

重写Authorize属性中的HandleUnauthorizedRequest方法。

例如:

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
   filterContext.Result = new RedirectToRouteResult(
                            new RouteValueDictionary (new {controller = "CustomError", action = "Unauthorized"}));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接