我有一些关于 HTTP 身份验证的基本问题
1)客户端如何知道服务器的HTTP认证类型(Basic/Digest/NTLM)?
这是在 HTTP 服务器端可配置的吗?
我的回答:服务器将设置它必须与客户端执行的身份验证类型。所以我们的客户端 API(在 C# HttpWebRequest API 中)会自动处理它。最好使用 Wireshrk 并应用 HTTP 过滤器;您将在 Internet 协议层获得源 IP 和目标 IP。以及http层的传输控制协议和认证类型的src和dest端口。
2)如果我在客户端和服务器之间放置 squid linux 代理;我的客户端代码是否还需要了解代理的身份验证类型?还是身份验证类型只与端 HTTP 服务器有关?
我的回答:如果 squid 代理放在 Client 和 Server 之间;它不会使用 HTTP 身份验证。它可以使用 a) DB:使用 SQL 数据库 b) LDAP:使用轻量级目录访问协议。c) RADIUS:使用 RADIUS 服务器进行登录验证。等等。所以我们不得不在 HTTP 标头中提到代理身份验证凭据。
3) 使用 WireShark 发现 Browser 到 Server 有 3 个请求来完成单个请求。
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 安全过滤器的 REST Java 服务器)。
我有 C# HTTP 客户端;
尽管设置了 System.Net.NetworkCredentials,但第一次发送 HttpWebRequest 时没有凭据;所以clinet用relam和nonce得到了407。
第二次 HttpWebRequest 是成功的。该客户端没有像浏览器一样的第三个请求。
为什么浏览器和 C# 客户端之间存在这种差异?
我的回答:我仍然不知道这里发生了什么:Q3。
4)现在我面临的真正问题是当 SQUID LINUX PROXY 进入我们的客户端和 HTTP 服务器之间时,浏览器执行了相同的三个请求身份验证并成功。但是,C# HttpWebRequest 在第二次请求时失败(401)并到达缓存(异常){} 块,第三次未尝试。
当代理服务器介于两者之间时,您能否请任何人澄清我如何在 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 标头中包含有关我们客户端 ip 的信息X-Forwarded-For
。
以下是可能的解决方案
仅当您的代理需要任何身份验证时才需要这些解决方案,否则忽略它。
解决方案 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了解有关代理身份验证的更多信息