4

我有一些关于 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了解有关代理身份验证的更多信息

4

1 回答 1

4

这是一个挑战/响应协议。通常,客户端发出一个没有任何身份验证标头的初始请求(您可以设置request.PreAuthenticate = true为在第一个请求中发送凭据)。

然后,服务器以它支持的身份验证方法列表进行响应。

如果用户没有使用 明确指定身份验证方法CredentialsCache,则运行时将尝试所有这些方法,从最强到最弱。某些协议(例如 NTLM)需要从客户端到服务器的多个请求。理论上,Digest 应该与一个单一的一起工作,不知道为什么它会发送两次请求。

关于您的代理问题,有两种不同的身份验证:

  1. 目标 Web 服务器的身份验证,代理只是简单地通过它,您的客户端不需要任何特殊代码。
  2. 除此之外,代理本身也可能需要身份验证——这可能与目标 Web 服务器不同。

您指定这些使用

var proxy = new WebProxy ("http://localhost:3128/");
proxy.Credentials = new NetworkCredential ("username", "password");

进而

WebRequest.DefaultWebProxy = proxy;

或者

request.Proxy = proxy;

WebProxy如果您的代理服务器不使用任何身份验证,请不要在 上设置任何凭据。

如果您在使用代理服务器时无法进行身份验证,请查看使用 Wireshark 在三方(Web 服务器、代理、客户端)之间发送的实际请求。

于 2013-02-01T09:49:17.537 回答