我有一些关于HTTP身份验证的基本问题
1)客户端如何了解HTTP的服务器身份验证类型(Basic / Digest / NTLM)?
这可以在HTTP Server端配置吗?
我的答案:服务器将设置它必须与客户端执行的身份验证类型。 因此,我们的客户端API(在C#HttpWebRequest API中)将自动处理它。 最好使用Wireshrk并应用HTTP过滤器;您将在Internet协议层获得源IP和目标IP。并且传输控制协议的src和dest端口以及http层的身份验证类型。
2)如果我在客户端和服务器之间放置squid linux proxy;是否有任何需要从我的客户端代码应该知道代理的身份验证类型?或身份验证类型仅与最终HTTP服务器相关?
我的回答:如果squid代理放在客户端和服务器之间;它不会使用HTTP身份验证。它可能使用a)DB:使用SQL数据库b)LDAP:使用轻量级目录访问协议。 c)RADIUS:使用RADIUS服务器进行登录验证。等等.. 因此,我们必须在HTTP标头中提及代理身份验证凭据。
3)使用WireShark发现浏览器到服务器有三个请求来满足单个请求。
a)浏览器发送没有任何身份验证凭据的请求;所以服务器响应401以及relam和nonce。
WWW-Authenticate: Digest realm="realm", qop="auth", nonce="MTM1OTYyMzkyNDU4MzpiOWM0OWY0NmMzMzZlMThkMDJhMzRhYmU5NjgwNjkxYQ=="\r\n <BR>
b)第二次浏览器发送带凭证,relam,nonce,cnonce的请求;但仍然服务器回复401;
WWW-Authenticate: Digest realm="realm", qop="auth", nonce="MTM1OTYyMzk0OTAyMTo3Njk3MDNhZTllZDQyYzQ5MGUxYzI5MWY2MGU5ZDg0Yw==", stale="true"\r\n
c)第三次浏览器使用相同的凭据,relam,nonce,cnonce发送相同的请求。这次服务器发送200 ok。
我的问题是第二次和第三次浏览器发送相同的请求;为什么服务器第二次失败并在第三次成功。这是因为我的服务器实现? (我正在使用带有SPRING Security过滤器的REST Java服务器)。
我有C#HTTP客户端;
虽然设置了System.Net.NetworkCredentials,但在没有凭据的情况下第一次发送HttpWebRequest;所以clinet得到407与relam和nonce。
第二次HttpWebRequest成功。此客户端没有第三个请求,例如浏览器。
为什么浏览器和C#客户端之间存在差异?
我的回答:我仍然不知道这里发生了什么:Q3。
4)现在我面临的真正问题是当我们的客户端和HTTP服务器之间出现SQUID LINUX PROXY时,浏览器执行了相同的三个请求身份验证并成功完成。但是,C#HttpWebRequest在第二个请求时失败(401)并到达缓存(异常){}块并且第三次没有尝试。
当你介绍PROXY SERVER时,有没有人可以请大家澄清一下如何在C#客户端解决这个问题?
下面的代码正在执行GET请求。
HttpWebRequest request = WebRequest.Create("url") as HttpWebRequest;
request.Credentials = new NetworkCredential(loginUserName, password);
WebResponse response = request.GetResponse();
请注意,我们的代理请求是通过TCP协议发送的,而不是HTTP协议。然后从PROXY到SERVER与HTTP协议进行通信。
但来自Proxy的HTTP请求在HTTP标头X-Forwarded-For
中有关于我们的客户端IP的信息。
这些解决方案仅在您的代理需要任何身份验证时才需要,否则请忽略它。
解决方案1:为我工作
request.Proxy.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
解决方案2:
IWebProxy proxy = WebRequest.GetSystemWebProxy();
proxy.Credentials = new NetworkCredential(UserName, UserPassword, UserDomain);
request.Proxy = proxy;
Martin提供的解决方案3:
var proxy = new WebProxy ("http://localhost:3128/");
proxy.Credentials = new NetworkCredential (UserName, UserPassword, UserDomain);
request.Proxy = proxy;
了解有关代理身份验证的详情 http://wiki.squid-cache.org/Features/Authentication
答案 0 :(得分:4)
这是一项挑战/响应协议。通常,客户端在没有任何身份验证标头的情况下发出初始请求(您可以设置request.PreAuthenticate = true
以使用第一个请求发送凭据)。
然后,服务器响应它支持的身份验证方法列表。
如果用户没有使用CredentialsCache
显式指定身份验证方法,则运行时将尝试所有方法,从最强到最弱。某些协议(例如NTLM)需要从客户端到服务器的多个请求。从理论上讲,Digest应该只使用一个,不知道它为什么要两次发送请求。
关于您的代理问题,有两种不同的身份验证:
您可以使用
指定这些内容var proxy = new WebProxy ("http://localhost:3128/");
proxy.Credentials = new NetworkCredential ("username", "password");
然后
WebRequest.DefaultWebProxy = proxy;
或
request.Proxy = proxy;
如果您的代理服务器不使用任何身份验证,请不要在WebProxy
上设置任何凭据。
如果在使用代理服务器时无法使用身份验证,请查看使用Wireshark在三方(Web服务器,代理,客户端)之间发送的实际请求。