今天,一位同事问我如何配置 IIS 7.5,以对一个简单的 Intranet 网站使用集成 Windows 身份验证和模拟,该网站仅包含仅限 Active Directory 中特定组(例如“管理员”)的静态内容。
事实证明,当经过身份验证的用户没有请求资源的权限时,IIS 会发送 HTTP 401 响应。权限被拒绝可能是 NTFS 文件 ACL 或 IIS 配置中定义的 system.webServer/security/authorization
ACL 造成的。
所有主流浏览器似乎都会将此 401 解释为最终用户提供了无效的 Windows 用户名/密码凭据,从而提示用户输入用户名/密码。 IE 似乎在显示 401 响应正文/内容之前提示最多 3 次。 Chrome 和 Safari 似乎会反复提示用户。
这可能会让最终用户感到困惑,他们不断重复输入有效的 Windows 用户名/密码,结果却再次收到提示。
更好的方法是让 IIS 返回 HTTP 403 而不是 HTTP 401:
403 Forbidden
The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated.
Source: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4
如何配置 IIS 集成 Windows 身份验证以发送 HTTP 401(表示登录失败)和 HTTP 403(表示权限被拒绝)?
最佳答案
什么不起作用
我尝试了几乎所有 IIS 配置排列,但没有成功。我摆弄了 Windows 身份验证提供程序设置,例如 NTLM、Negotiate 和 Negotiate:Kerberos。他们似乎都没有成功。这并不奇怪,因为浏览器决定再次尝试身份验证,尽管它们可能不应该这么做。
401 Unauthorized
The request requires user authentication. The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource. The client MAY repeat the request with a suitable Authorization header field (section 14.8). If the request already included Authorization credentials, then the 401 response indicates that authorization has been refuse for those credentials.
Source: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2
什么有效
我决定利用一些低劣和肮脏的 ASP.NET 来解决这个问题。下面借助服务器上的几个文本文件和 ASP.NET 动态编译来实现响应重写。 (我以前从未使用过动态编译,但是,对于静态站点来说,编译似乎有点大材小用。)
下面的 Global.asax 文件会 Hook EndRequest 事件,如果用户成功验证为 Windows 用户,则将 HTTP 401 响应重写为 HTTP 403,但是,由于某些其他原因,请求被拒绝(我假设原因必须是是授权失败)。
web.config 文件包含用于通过 ASP.NET 管道路由所有请求的条目,并拒绝任何非“销售”Windows 组成员的经过身份验证的用户的访问。
此解决方案假设您有一个在 IIS 集成管道模式(即非经典模式)下运行的应用,您启用了 Windows 身份验证,并禁用了所有其他身份验证方案。
/Global.asax:
<Script language="C#" runat="server">
void Application_EndRequest() {
// rewrite HTTP 401s to HTTP 403s if the user is authenticated using
// integrated Windows auth with impersonation, but,
// the user lacks permissions to the requested URL
if (Context.User != null &&
Context.User.Identity != null &&
Context.User.Identity.IsAuthenticated &&
Context.User is System.Security.Principal.WindowsPrincipal &&
Context.Response.StatusCode == 401)
{
Context.Response.Clear();
Context.Response.StatusCode = 403;
}
}
</script>
/web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<security>
<authorization>
<remove users="*" roles="" verbs="" />
<add accessType="Allow" roles="Sales" />
</authorization>
</security>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
</configuration>
为了将来的引用,我创建了一个要点@ https://gist.github.com/steve-jansen/6234700
关于asp.net - 将 IIS Windows 身份验证配置为返回 HTTP 403 而不是 HTTP 401,以拒绝经过身份验证的用户的权限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18241640/