即使此 HTTPS WebRequest 在浏览器中有效,但是什么导致它超时?

发布于 2024-10-31 18:58:19 字数 992 浏览 0 评论 0原文

这是我的请求:

var request = (HttpWebRequest) WebRequest.Create("https://mtgox.com/");
request.CookieContainer = new CookieContainer();
request.AllowAutoRedirect = false;
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
request.Headers[HttpRequestHeader.AcceptEncoding] = "gzip, deflate";
request.Headers[HttpRequestHeader.AcceptLanguage] = "en-gb,en;q=0.5";
request.Headers[HttpRequestHeader.AcceptCharset] = "ISO-8859-1,utf-8;q=0.7,*;q=0.7";
request.Timeout = 5000;
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0";
request.Method = "GET";

request.GetResponse();

标头是使用 HttpFox 从 Firefox 复制的。我使用 Fiddler2 来验证至少对于 HTTP 请求,Firefox 请求和我的请求之间的标头完全相同。

但是,当使用 HTTPS 向此特定网站执行请求时,请求就会超时。它适用于其他网站。

我必须以与 Firefox 不同的方式执行它,因为它总是在 Firefox 中运行。但是,我无法使用 Fiddler2 对其进行调试,因为每当 Fiddler2 转发这些请求时,它们也会超时,即使是由 Firefox 发起的也是如此。

这只是一个真正有缺陷的网站吗?上面的哪一部分暴露了我不是 Firefox?

Here's my request:

var request = (HttpWebRequest) WebRequest.Create("https://mtgox.com/");
request.CookieContainer = new CookieContainer();
request.AllowAutoRedirect = false;
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
request.Headers[HttpRequestHeader.AcceptEncoding] = "gzip, deflate";
request.Headers[HttpRequestHeader.AcceptLanguage] = "en-gb,en;q=0.5";
request.Headers[HttpRequestHeader.AcceptCharset] = "ISO-8859-1,utf-8;q=0.7,*;q=0.7";
request.Timeout = 5000;
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0";
request.Method = "GET";

request.GetResponse();

The headers were copied from Firefox using HttpFox. I used Fiddler2 to verify that at least for HTTP requests, the headers are completely identical between Firefox requests and my requests.

However, when performing a request to this specific website using HTTPS, the request simply times out. It works for other websites.

I must be performing it differently to Firefox, because it always works in Firefox. I can't debug it using Fiddler2, however, because whenever Fiddler2 forwards these requests they also time out, even when originated by Firefox.

Is it just a really buggy website? Which part of the above gives me away as not being Firefox?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

尸血腥色 2024-11-07 18:58:19

使用 Microsoft Network Monitor,我发现 HttpWebRequest 会陷入应该发回客户端密钥交换的阶段。事实并非如此。服务员按时等待,但始终没有到来。

解决这个问题的方法是强制 HttpWebRequest 使用 SSL3 而不是 TLS(尽管 TLS 应该在必要时自动转换为 SSL3):

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

为什么会这样,我想我永远不会知道 - 只是那些需要更多时间的神秘事情之一弄清楚比我认识的任何人都愿意花的钱...

捕获的一件事有所不同:TLS 变体 服务器 Hello 响应中有一个“警报”条目,该条目在 SSL3 交换以及所有实际有效的 TLS 交换中均不存在。但奇怪的是,在 Firefox 成功执行请求的捕获中也出现了相同的警报。

最后,当我第一次发布这个问题时,似乎出现了一个临时的 OCSP 故障,但现已解决。这增加了混乱,但不是核心问题。

Using Microsoft Network Monitor, I found that HttpWebRequest would get stuck at a stage where it's supposed to send back a client key exchange. It simply didn't. The server duly waited for it, but it never came.

What fixed it was forcing HttpWebRequest to use SSL3 instead of TLS (even though TLS is supposed to automatically turn into SSL3 if necessary):

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

Why this is so I guess I'll never know - just one of those mysterious things that would take more time to figure out than anyone I know is willing to spend...

One thing that was different about the captures: the TLS variant had an "Alert" entry in the Server Hello response, which is absent from the SSL3 exchange and also from all the TLS exchanges that actually worked. Curiously, though, the same alert is present in a capture of Firefox performing the request successfully.

Finally, it appears that there was a temporary OCSP glitch just when I was first posting this question, which has since been resolved. This added to the mess, but isn't the core problem.

尝蛊 2024-11-07 18:58:19

HttpWebRequest/HttpWebReponse 调用超时错误的典型原因是“未关闭响应对象/流”,这使连接保持活动状态。读取流的内容后,您只需关闭 Stream 对象或 HttpWebResponse 对象即可。默认连接限制为 2。

HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
Stream stream = webResponse.GetResponseStream();
string responseString = ((TextReader)new StreamReader(stream)).ReadToEnd();
webResponse.Close();

或者,如果您在将被许多用户同时调用的 Web 服务中实现逻辑,那么您可能需要考虑增加 HttpWebRequest 对象中的连接限制。

HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(url);    
webRequest.ServicePoint.ConnectionLimit = 20;

The typical reason for timeout errors with HttpWebRequest/HttpWebReponse calls is "not closing the response object/stream", which keep the connections active. You have to simply close the Stream object or the HttpWebResponse object after reading the contents of the stream. Default connection-limit is 2.

HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
Stream stream = webResponse.GetResponseStream();
string responseString = ((TextReader)new StreamReader(stream)).ReadToEnd();
webResponse.Close();

Alternatively, if you implemented your logic in a web-service which will be concurrently invoked by many users, then you may want to consider increasing the connection-limit in HttpWebRequest object.

HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(url);    
webRequest.ServicePoint.ConnectionLimit = 20;
缪败 2024-11-07 18:58:19

Windows 7 上的 .NET 框架实现了 TLS 扩展:服务器名称指示 (RFC4366)。根据您的帖子此 TLS 警报意味着什么,服务器响应为“无法识别的名字”。不知道为什么连接会报告超时,因为它确实没有。您的网络跟踪应该显示客户端在此 [FIN,ACK] 之后发起连接终止。降级到 SSL3 可以避免调用 SNI。

仅供参考:Windows XP 上的同一 .NET 框架不使用 TLS 服务器名称指示扩展。你的程序将在那里工作......

就我而言,我将这种情况的发生追溯到 Apache 中缺少的 ServerName 指令。将 ServerName 添加到 SSL 配置中解决了这个问题,因为现在 Web 服务器不再不知道其名称。

The .NET framework on Windows 7 implements a TLS extension: Server Name Indication (RFC4366). According to your post What does this TLS Alert mean the server is responding with "Unrecognized Name". Not sure why the connection is reported to time out, because it really doesn't. Your network traces should show that the client initiates a connection termination after this [FIN,ACK]. Downgrading to SSL3 avoids the invocation of the the SNI.

FYI: The same .NET framework on Windows XP does not use the TLS Server Name Indication Extension. Your program will work there....

In my case I traced the occurrence of this to a missing ServerName directive in Apache. Adding the ServerName to the SSL configuration solved it, because now the web server no longer is unaware of its name.

撩起发的微风 2024-11-07 18:58:19

最近发现了同样的问题,并想看看 Microsoft 是否可以在较新的 .net 版本中修复此问题。这是我测试的代码(出于隐私原因删除了域):

HttpWebRequest request =
    (HttpWebRequest)WebRequest.Create("https://www.xxSomeDomainNamexx.com/");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
Console.WriteLine(reader.ReadToEnd());

针对 .net 版本 2.0、3.0 和 3.5 编译此代码,所有代码似乎都表现出与这里每个人都在讨论的完全相同的行为。然后我尝试针对 4.0 和 4.5 进行编译,并在两个地方都收到了正确的响应。

基于此,微软似乎已经在较新的 .net 版本中解决了这个问题。为了后代,我还测试了 enverpex 建议的 SecurityProtocol 更改,它在 2.0、3.0 和 3.5 上运行得很好。

Recently found out about this same problem, and wanted to see if Microsoft might have fixed this in newer .net versions. This is the code I tested with (domain removed for privacy):

HttpWebRequest request =
    (HttpWebRequest)WebRequest.Create("https://www.xxSomeDomainNamexx.com/");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
Console.WriteLine(reader.ReadToEnd());

Compiled this against .net versions 2.0, 3.0, and 3.5 and all seemed to exhibit the exact same behavior as everyone here has been discussing. Then I tried compiling against 4.0 and 4.5, and received proper responses in both places.

Based on this, it seems Microsoft has likely fixed this problem in newer .net versions. For posterity I also tested the SecurityProtocol change suggested by enverpex and it worked great on 2.0, 3.0, and 3.5.

冰葑 2024-11-07 18:58:19

我对 https 请求也遇到了同样的超时问题,但没有一个答案对我有帮助。刚才我找到了一个解决方案,为我解决了这个问题。请注意,这仅适用于 .net Framework 4.5 或更高版本。

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
var response = WebRequest.Create("https://yoursecurewebservice").GetResponse();
var body = new StreamReader(response.GetResponseStream()).ReadToEnd();
Console.WriteLine(body);

I had the same timeout issue with https requests and none of the answers helped me. Just now I found a solution that resolved the problem for me. Note that this works only with .net framework 4.5 or higher.

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
var response = WebRequest.Create("https://yoursecurewebservice").GetResponse();
var body = new StreamReader(response.GetResponseStream()).ReadToEnd();
Console.WriteLine(body);
羁〃客ぐ 2024-11-07 18:58:19

HTTPS 客户端很可能无法验证该服务器提供的证书链,例如由于缺少根证书或无法访问 OCSP 响应程序。即,您使用的浏览器和 HTTPS 客户端中可能有不同的配置。

作为选项之一,您可以使用我们的 HTTPBlackbox 组件的试用版并尝试使用 TElHTTPSClient 进行连接。它将为您提供详细的错误信息(如果出现错误),以便您能够确定 HttpWebRequest 出了什么问题。

Most likely the HTTPS client can't validate the certificate chain presented by this server, for example due to missing root certificate or inaccessible OCSP responder. I.e. there can be something different configured in the browser and in HTTPS client you use.

As one of the options you can take a trial version of our HTTPBlackbox components and try to connect using TElHTTPSClient. It will give you detailed error information (in case of error) so you will be able to determine, what's wrong with HttpWebRequest.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文