【问题标题】:Https GET request passes in Postman and browser but fails in codeHttps GET 请求在 Postman 和浏览器中通过但在代码中失败
【发布时间】:2019-07-25 12:59:10
【问题描述】:

我正在尝试通过使用 .Net 4.5 的 rest API 获取 JSON
我在代码中尝试了各种方法,但最终我得到了:

"验证失败,因为远程方已关闭 传输流”。

完全相同的 URL 可通过浏览器和 Postman 工作。

到目前为止,我已经尝试使用 .Net 的 WebClient、HttpClient 和 HttpWebRequest,结果相同。我尝试比较 Postman 和我的代码之间的请求(通过 RequestBin),但即使它们相同,我仍然会不断返回:

身份验证失败,因为远程方已关闭 交通

我当前的代码使用的是 HttpWebRequest,但每个解决方案都可以。

我已经使用了所有的安全协议,其中一些会导致 API 返回404,而另一些会导致服务器返回

"验证失败,因为远程方已关闭 传输流”。

这是我当前的代码:

public string GetCityStreets()
{
    var url = "https://data.gov.il/api/action/datastore_search?resource_id=a7296d1a-f8c9-4b70-96c2-6ebb4352f8e3&q=26";
    var request = (HttpWebRequest)WebRequest.Create(url);
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 |
                                           SecurityProtocolType.Tls12 |
                                           SecurityProtocolType.Tls11 |
                                           SecurityProtocolType.Tls;

    var response = (HttpWebResponse)request.GetResponse();
    string jsonResponse;

    using (var reader = new StreamReader(response.GetResponseStream()))
    {
         jsonResponse = reader.ReadToEnd();
    }
    return jsonResponse;
}

在我当前的代码中,实际发出请求时会引发异常:request.GetResponse()
本质上,我需要的是从 API 中获取 JSON。

【问题讨论】:

  • 你在什么操作系统上运行?

标签: c# ssl httpwebrequest


【解决方案1】:

设置SecurityProtocolType.Tls12初始化请求之前:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12` 
var request = WebRequest.CreateHttp(url);

如果您使用的是 Windows 7。在 Windows 10 上,您应该只需要 SecurityProtocolType.SystemDefault


注意:要启用TLS1.3(Windows 7 和 Windows 10 都可用),如果您不使用.Net 4.8.Net Core 3.0,因为它没有枚举器,你可以设置它:

var secProtoTls13 = (SecurityProtocolType)12288;

删除您在此处设置的所有其他SecurityProtocolType

设置User-Agent 标头也是强制性的,否则您将收到404(未找到)。这是 FireFox 标头:

request.UserAgent = "Mozilla/5.0 (Windows NT 10; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0";

关于 User-Agent 标头的说明:此特定站点不会激活 HTTP Strict Transport Security (HSTS)。但是有些网站会这样做,当他们看到 WebBrowser 支持它时。 HttpWebRequest 不理解它,因此它只会等待永远不会出现的响应,因为站点正在等待交互
您可能想改用 IE11 标头。

另外添加这个标题:

 request.Headers.Add(HttpRequestHeader.CacheControl, "no-cache");

【讨论】:

  • 做到了!但结合@mjwills 回答。如果没有更改用户代理,它仍然无法正常工作。谢谢!
  • 是的,我知道它需要一个用户代理。我已经测试过了。没有它(顺便说一句,这很常见)该网站拒绝进一步前进,只是回复404
  • 查看我添加的关于用户代理的注释。您可能会发现调试 undefined 连接问题很重要。
【解决方案2】:

服务器端似乎正在检查用户代理(大概是为了阻止机器人和其他代码(比如你的!)访问端点)。要绕过这一点,您需要将用户代理设置为一个值,使其认为您是网络浏览器。

request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36";

工作,例如。

您可能希望考虑设置ServicePointManager.SecurityProtocol仅一次(在应用启动时)而不是在每个请求上。

【讨论】:

    【解决方案3】:

    这适用于 HttpClient(.net 4.5 及更高版本)

        var url = "https://data.gov.il/api/action/datastore_search?resource_id=a7296d1a-f8c9-4b70-96c2-6ebb4352f8e3&q=26";
        var client = new HttpClient();
        client.DefaultRequestHeaders.Add("User-Agent", "C# App");
        Task<string> response =  client.GetStringAsync(url);
        Console.WriteLine(response.Result); 
    

    认为服务器需要用户代理。

    【讨论】:

    • 这也有效,但只能添加 'ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;'在创建客户端之前。谢谢!
    猜你喜欢
    • 2021-11-23
    • 2020-07-29
    • 2016-07-11
    • 2018-06-05
    • 2018-06-30
    • 2019-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多