什么没有奏效
我尝试了几乎所有 IIS 配置排列,但都没有运气。我玩弄了 Windows 身份验证提供程序设置,例如 NTLM、Negotiate 和 Negotiate:Kerberos。他们似乎都没有成功。这并不奇怪,因为浏览器决定再次尝试身份验证,即使他们可能不应该这样做。
401未经授权
该请求需要用户身份验证。响应必须包含一个 WWW-Authenticate 头字段(第 14.47 节),其中包含适用于所请求资源的质询。客户端可以使用合适的授权头域重复请求(第 14.8 节)。如果请求已包含授权凭证,则 401 响应指示已拒绝对这些凭证的授权。
来源:http ://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2
什么起作用了
我决定利用一些肮脏的 ASP.NET 来解决这个问题。下面借助服务器上的几个文本文件和 ASP.NET 动态编译实现响应重写。(我以前从未使用过动态编译,但是对于静态站点来说,编译似乎有点过头了。)
下面的 Global.asax 文件挂钩 EndRequest 事件,如果用户成功通过身份验证为 Windows 用户,则将 HTTP 401 响应重写为 HTTP 403,但是由于某些其他原因,请求被拒绝(我认为原因必须是授权失败)。
web.config 文件包含通过 ASP.NET 管道路由所有请求的条目,并拒绝任何不是“Sales”Windows 组成员的经过身份验证的用户的访问。
此解决方案假定您有一个在 IIS 集成管道模式(即非经典模式)下运行的应用程序,您启用了 Windows 身份验证,并禁用了所有其他身份验证方案。
/全球.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>
为了将来参考,我创建了一个 Gist @
https://gist.github.com/steve-jansen/6234700