Intranet和匿名用户的IIS站点

时间:2013-11-27 14:18:43

标签: asp.net authentication iis

我正在开发一个应该可供在自己帐户下运行的Intranet用户使用的应用程序(Windows身份验证)。这很容易配置并且有效。

现在,如果用户未登录到域(因为他们不在现场或未登录的设备上),他们仍然可以使用该应用程序,减去一些个性化功能。

总而言之,这就是我想要发生的事情:

  1. 用户打开应用程序。如果Windows凭据可用,浏览器会将它们发送到IIS。
  2. 如果收到用户凭据,则应用程序在这些凭据下运行(我已经覆盖了这些凭据)。
  3. 如果未收到用户凭据,则应用程序将在IIS匿名帐户下运行,并且个性化功能已关闭(我已完成此操作)。
  4. 我无法工作的是可选择发送凭据。如果我打开Windows身份验证,我将登录,这很好。但是,如果我尝试访问网站而不发送凭据,我将获得401,这是有道理的。所以我打开匿名身份验证,现在永远不会发送凭据。

    这实际上是有道理的,因为IIS从不要求从浏览器进行身份验证。问题是,如何使这种情况有效?

1 个答案:

答案 0 :(得分:3)

你的分析是正确的。 HTTP authentication计划是:

  • 匿名访问
  • 挑战 - 响应身份验证
    • 谈判(Kerberos)
    • NTLM
    • 摘要
  • 基本身份验证

在IIS(以及大多数HTTP服务器)上,默认身份验证过程遵循上述顺序。即。如果匿名访问成功(此处不会详细说明),即使启用了其他身份验证提供程序,也会被忽略。

HTTP 401挑战

如果要管理多种身份验证方法和提供程序,则必须使用在您认为凭据无效时拒绝凭据的机制。您可以通过发送401响应来实现此目的。这称为HTTP 401 Challenge

这个想法是告诉客户端(浏览器)拒绝用于所请求资源的凭据。

根据方案和客户端配置,客户端可以处理身份验证。在这种情况下,身份验证过程可能会有所不同:质询 - 响应提供程序需要一定数量的交换才能验证凭据。

无论如何,在您的情况下,启用匿名访问后,浏览器会将第一个401响应解释为"此请求需要身份验证"。如果在服务器端启用了服务器,则服务器会自动在响应头中包含支持的身份验证提供程序。

HTTP/1.1 401 Unauthorized
Server: Microsoft-IIS/7.5
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
WWW-Authenticate: Digest qop="auth",algorithm=MD5-sess,nonce="+Upgraded+v1b3a89710edce01754fd608...",charset=utf-8,realm="Digest"
WWW-Authenticate: Basic realm="host"
X-Powered-By: ASP.NET
Content-Length: 0
Proxy-Support: Session-Based-Authentication

如果您的浏览器已正确配置为发送Web应用程序区域的凭据(您这么说),它会自动使用它知道的第一个身份验证提供程序(例如NTLM)并重新启动 - 使用它知道的凭据处理请求(在您的情况下为Windows凭据)。

GET http://host/yourpage.aspx HTTP/1.1
Accept-Encoding: gzip, deflate
Authorization: NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAFASgKAAAADw==
Connection: Keep-Alive

当身份验证过程失败时,服务器会自动向客户端发送403 Forbidden响应以避免过多流量。 403响应可以阻止挑战。好消息是它需要一些挑战:超过4个。 通常,HTTP身份验证挑战需要接近3个Challenge-Response最大值才能成功(NTLM为3,Negotiate -Kerberos-为2)。

由于您允许匿名访问,因此服务器不会阻止客户端请求,并且将使用匿名凭据调用您的页面。您仍然可以自己设置HTTP Response Code,从而在您的网页中与您的客户进行互动。如前所述,除了Anonymous之外,它只能启用另一个身份验证提供程序。

所以诀窍是用你服务器端的计数器来处理它并说'#34;如果我的auth session / cookie计数器超过3,我的客户端就不能对服务器进行身份验证。让我们说他是匿名的"。

部分代码

我没有完全按照您的需要做,但您可以调整我的代码:

    int i = 3;
    int j = 0;
    HttpContext httpContext = HttpContext.Current;

    // Record authentication process
    HttpCookie httpCookie2 = httpContext.Request.Cookies["loginAttemptCount"];
    if (httpCookie2 == null || httpCookie2.Value == String.Empty)
    {
        httpCookie2 = new HttpCookie("loginAttemptCount");
    }
    else
    {
        j = Int32.Parse(httpCookie2.Value, System.Globalization.CultureInfo.InvariantCulture);
    }

    j = (j + 1) % i;

    string user = Request.ServerVariables["LOGON_USER"];

    // Send 401 responses to authenticate the user
    if (j != 0 && user == String.Empty)
    {
        httpCookie2.Value = j.ToString(System.Globalization.CultureInfo.InvariantCulture);
        httpContext.Response.Cookies.Add(httpCookie2);
        Response.StatusCode = 401;
        return;
    }

    httpCookie2.Value = String.Empty;
    httpContext.Response.Cookies.Add(httpCookie2);

如果需要,您可以在Authorization标题中查看授权提供商。

Request.Headers["Authorization"]

您可以使用Fiddler来跟踪您的HTTP标头。

希望它足够清楚。