我正在开发一个应该可供在自己帐户下运行的Intranet用户使用的应用程序(Windows身份验证)。这很容易配置并且有效。
现在,如果用户未登录到域(因为他们不在现场或未登录的设备上),他们仍然可以使用该应用程序,减去一些个性化功能。
总而言之,这就是我想要发生的事情:
我无法工作的是可选择发送凭据。如果我打开Windows身份验证,我将登录,这很好。但是,如果我尝试访问网站而不发送凭据,我将获得401,这是有道理的。所以我打开匿名身份验证,现在永远不会发送凭据。
这实际上是有道理的,因为IIS从不要求从浏览器进行身份验证。问题是,如何使这种情况有效?
答案 0 :(得分:3)
你的分析是正确的。 HTTP authentication计划是:
在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标头。
希望它足够清楚。