C# HTTP 407(需要代理身份验证)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14641492/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HTTP 407 (Proxy Authentication Required)
提问by Kanagavelu Sugumar
I have some basic questions on HTTP authentication
我有一些关于 HTTP 身份验证的基本问题
1) How does client know about Server's authentication type (Basic/Digest/NTLM) of HTTP ?
is this configurable at HTTP Server side?
1) 客户端如何知道服务器的 HTTP 认证类型(Basic/Digest/NTLM)?
这可以在 HTTP 服务器端配置吗?
My Answer:Server will be set with which authentication type it has to perform with the client. So our client API(in C# HttpWebRequest API) will automatically take care of it. Best use of Wireshrk with applying HTTP filter; you will get source and Destination IP at Internet Protocol layer. And src and dest port at Transmission control protocol and athentication type at http layer.
我的回答:服务器将设置它必须与客户端执行的身份验证类型。所以我们的客户端 API(在 C# HttpWebRequest API 中)会自动处理它。最佳使用 Wireshrk 并应用 HTTP 过滤器;您将在 Internet 协议层获得源和目标 IP。以及传输控制协议和http层的认证类型的src和dest端口。
2) If i place squid linux proxy in between client and Server; is there any need from my client code should know about authentication type of proxy also? or authentication type is only related to the end HTTP server?
2)如果我将squid linux代理放在客户端和服务器之间;我的客户端代码是否还需要了解代理的身份验证类型?还是认证类型只和端HTTP服务器有关?
My Answer:If squid proxy is placed in between Client and Server; it wont use HTTP authentication. It may use a) DB: Uses a SQL database b) LDAP: Uses the Lightweight Directory Access Protocol. c) RADIUS: Uses a RADIUS server for login validation. and etc.. So we have to mention proxy authentication credentials in HTTP Headers.
我的回答:如果squid代理放在Client和Server之间;它不会使用 HTTP 身份验证。它可以使用 a) DB:使用 SQL 数据库 b) LDAP:使用轻量级目录访问协议。c) RADIUS:使用 RADIUS 服务器进行登录验证。等等。所以我们必须在HTTP Headers中提到代理身份验证凭据。
3) Using WireShark found that there are three request from Browser to Server to fulfill single request.
3) 使用 WireShark 发现从浏览器到服务器有三个请求来完成单个请求。
a) Browser sends a request without any authentication credentials; So server responded with 401 along with relam and nonce.
a) 浏览器在没有任何身份验证凭据的情况下发送请求;所以服务器响应 401 以及 relam 和 nonce。
WWW-Authenticate: Digest realm="realm", qop="auth", nonce="MTM1OTYyMzkyNDU4MzpiOWM0OWY0NmMzMzZlMThkMDJhMzRhYmU5NjgwNjkxYQ=="\r\n <BR>
b) The second time Browser sends request with credentials, relam, nonce, cnonce; but still server responded with 401;
b) 浏览器第二次发送带有凭证的请求,relam,nonce,cnonce;但服务器仍以 401 响应;
WWW-Authenticate: Digest realm="realm", qop="auth", nonce="MTM1OTYyMzk0OTAyMTo3Njk3MDNhZTllZDQyYzQ5MGUxYzI5MWY2MGU5ZDg0Yw==", stale="true"\r\n
c) The third time Browser send the same request with same credentials, relam, nonce, cnonce. This time Server sends 200 ok.
c) 第三次浏览器使用相同的凭据发送相同的请求,relam、nonce、cnonce。这次服务器发送 200 ok。
My Question is in the second and third time Browser send the same request; why Server failed at second time and success at the third time. Is this because of my server implementation ? (I am having REST Java server with SPRING Security filter).
我的问题是第二次和第三次浏览器发送相同的请求;为什么服务器第二次失败而第三次成功。这是因为我的服务器实现吗?(我有带有 SPRING 安全过滤器的 REST Java 服务器)。
I have C# HTTP client;
我有 C# HTTP 客户端;
where in the first time HttpWebRequest is sent without credentials though the System.Net.NetworkCredentials is set; so clinet got 407 with relam, and nonce.
The second time HttpWebRequest is scuccess. There is no third request from this client like browser.
尽管设置了 System.Net.NetworkCredentials,但第一次在没有凭据的情况下发送 HttpWebRequest;所以clinet用relam和nonce得到了407。
第二次 HttpWebRequest 成功。没有来自这个客户端的第三个请求,比如浏览器。
Why this difference between the browser and C# client?
为什么浏览器和 C# 客户端之间存在这种差异?
My Answer:I am still don't know what is happening here: Q3.
我的回答:我仍然不知道这里发生了什么:Q3。
4) Now the real issue i am facing is When SQUID LINUX PROXY came in between our Client and HTTP Server, Browser did the same three request authentication and succeeded. However C# HttpWebRequest is failed (401) at the second request and reached the cache(exception){} block and not tried for the third time.
Could you please anyone clarify me how to resolve this issue in C# client when PROXY SERVER is in between?
4) 现在我面临的真正问题是当 SQUID LINUX 代理进入我们的客户端和 HTTP 服务器之间时,浏览器执行了相同的三个请求身份验证并成功。但是,C# HttpWebRequest 在第二次请求时失败 (401) 并到达缓存(异常){} 块并且没有第三次尝试。
当代理服务器介于两者之间时,您能否请任何人澄清我如何在 C# 客户端中解决此问题?
Below code is doing the GET Request.
下面的代码正在执行 GET 请求。
HttpWebRequest request = WebRequest.Create("url") as HttpWebRequest;
request.Credentials = new NetworkCredential(loginUserName, password);
WebResponse response = request.GetResponse();
Note that our request to proxy is send via TCP protocol not with HTTP protocol. Then from PROXY to SERVER is communicated with HTTP protocol.
But HTTP request from Proxy has the info about our client ip in the HTTP header X-Forwarded-For
.
请注意,我们对代理的请求是通过 TCP 协议而不是 HTTP 协议发送的。然后从 PROXY 到 SERVER 用 HTTP 协议进行通信。但是来自代理的 HTTP 请求在 HTTP 标头中有关于我们客户端 IP 的信息X-Forwarded-For
。
Below are the possible solutions
以下是可能的解决方案
These solutions only required if your proxy requires any authentication else ignore it.
Solution 1: working for me
仅当您的代理需要任何身份验证时才需要这些解决方案,否则忽略它。
解决方案 1:为我工作
request.Proxy.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
Solution 2:
解决方案2:
IWebProxy proxy = WebRequest.GetSystemWebProxy();
proxy.Credentials = new NetworkCredential(UserName, UserPassword, UserDomain);
request.Proxy = proxy;
Solution 3 given by Martin:
Martin给出的解决方案3:
var proxy = new WebProxy ("http://localhost:3128/");
proxy.Credentials = new NetworkCredential (UserName, UserPassword, UserDomain);
request.Proxy = proxy;
Learn more about proxy authentication at http://wiki.squid-cache.org/Features/Authentication
在http://wiki.squid-cache.org/Features/Authentication了解有关代理身份验证的更多信息
采纳答案by Martin Baulig
It's a challenge/response protocol. Usually, the client makes an initial request without any authentication headers (you may set request.PreAuthenticate = true
to send the credentials with the first request).
这是一个质询/响应协议。通常,客户端会在没有任何身份验证标头的情况下发出初始请求(您可以设置request.PreAuthenticate = true
为在第一个请求中发送凭据)。
Then, the server responds with a list of authentication methods that it supports.
然后,服务器用它支持的身份验证方法列表进行响应。
If the user did not explicitly specify an authentication method using CredentialsCache
, the runtime will try them all, from strongest to weakest. Some protocols (NTLM, for instance) require multiple requests from client to server. In theory, Digest should work with a single one, no idea why it's sending the request twice.
如果用户没有使用 明确指定身份验证方法CredentialsCache
,运行时将尝试所有方法,从最强到最弱。某些协议(例如 NTLM)需要从客户端到服务器的多个请求。理论上,Digest 应该只处理一个,不知道为什么它会发送两次请求。
Regarding your proxy question, there are two different kinds of authentication:
关于您的代理问题,有两种不同的身份验证:
- The target web server's authentication, a proxy simply passes this though and you don't need any special code in your client.
- In addition to that, the proxy itself may also require authentication - which may be different from the one of target web server.
- 目标 Web 服务器的身份验证,代理只是简单地传递它,您不需要在客户端中使用任何特殊代码。
- 除此之外,代理本身也可能需要身份验证 - 这可能与目标 Web 服务器之一不同。
You specify these using
您指定这些使用
var proxy = new WebProxy ("http://localhost:3128/");
proxy.Credentials = new NetworkCredential ("username", "password");
and then
进而
WebRequest.DefaultWebProxy = proxy;
or
或者
request.Proxy = proxy;
Don't set any credentials on the WebProxy
if your proxy server doesn't use any authentication.
WebProxy
如果您的代理服务器不使用任何身份验证,请不要在 上设置任何凭据。
If you can't get authentication working while using a proxy server, look at the actual requests that are being sent between the three parties (web server, proxy, client) with Wireshark.
如果在使用代理服务器时无法进行身份验证,请查看使用 Wireshark 在三方(Web 服务器、代理、客户端)之间发送的实际请求。