使用HttpClient进行Https调用

时间:2014-03-07 13:40:13

标签: c# asp.net-web-api

我一直在使用HttpClient来使用C#进行WebApi调用。看起来很整洁快速方式与WebClient相比。但是,在拨打Https电话时,我被困住了。

如何制作Https以下代码?

HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("https://foobar.com/");
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/xml"));

var task = httpClient.PostAsXmlAsync<DeviceRequest>(
                "api/SaveData", request);

编辑1: 上面的代码适用于进行http调用。但是,当我将方案更改为https时,它不起作用。这是获得的错误:

  

基础连接已关闭:无法建立信任   SSL / TLS安全通道的关系。

编辑2: 将方案更改为https是:第一步。

  

我如何提供证书&amp;公钥/私钥以及C#   请求。

13 个答案:

答案 0 :(得分:153)

如果服务器仅支持更高的TLS版本(如TLS 1.2),则它仍然会失败,除非您的客户端PC默认配置为使用更高的TLS版本。要解决此问题,请在代码中添加以下内容。

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

修改示例代码,它将是

HttpClient httpClient = new HttpClient();   

//specify to use TLS 1.2 as default connection
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

httpClient.BaseAddress = new Uri("https://foobar.com/");
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));

var task = httpClient.PostAsXmlAsync<DeviceRequest>("api/SaveData", request);

答案 1 :(得分:121)

只需在URI中指定HTTPS。

new Uri("https://foobar.com/");

Foobar.com需要拥有受信任的SSL证书,否则您的呼叫将因不受信任的错误而失败。

编辑答案:ClientCertificates with HttpClient

WebRequestHandler handler = new WebRequestHandler();
X509Certificate2 certificate = GetMyX509Certificate();
handler.ClientCertificates.Add(certificate);
HttpClient client = new HttpClient(handler);

编辑答案2:如果您连接的服务器已禁用SSL,TLS 1.0和1.1,并且您仍在运行.NET framework 4.5(或更低版本),则需要做出选择

  1. 升级到.Net 4.6+(Supports TLS 1.2 by default
  2. 添加注册表更改以指示4.5通过TLS1.2进行连接(请参阅:salesforce writeup以获取compat和密钥以更改或结帐IISCrypto请参阅Ronald Ramos answer comments
  3. 添加应用程序代码以手动配置.NET以通过TLS1.2进行连接(请参阅Ronald Ramos answer

答案 2 :(得分:13)

您的代码应该以这种方式修改:

httpClient.BaseAddress = new Uri("https://foobar.com/");

您只需使用https: URI方案即可。 MSDN上有一个关于安全HTTP连接的有用页面here。事实上:

  

使用https:URI方案

     

HTTP协议定义了两种URI方案:

     

http:用于未加密的连接。

     

https:用于应加密的安全连接。此选项还使用数字证书和证书颁发机构来验证服务器是否为其声称的用户。

此外,请考虑HTTPS连接使用SSL证书。确保您的安全连接具有此证书,否则请求将失败。

修改

  

以上代码适用于进行http调用。但是当我改变了   计划到https它不起作用,让我发布错误。

这是什么意思不起作用?请求失败了吗?抛出异常?澄清你的问题。

如果请求失败,则问题应该是SSL证书。

要解决此问题,您可以使用课程HttpWebRequest,然后使用其属性ClientCertificate。 此外,您可以找到here有关如何使用证书发出HTTPS请求的有用示例。

以下示例如下所示(如之前链接的MSDN页面所示):

//You must change the path to point to your .cer file location. 
X509Certificate Cert = X509Certificate.CreateFromCertFile("C:\\mycert.cer");
// Handle any certificate errors on the certificate from the server.
ServicePointManager.CertificatePolicy = new CertPolicy();
// You must change the URL to point to your Web server.
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://YourServer/sample.asp");
Request.ClientCertificates.Add(Cert);
Request.UserAgent = "Client Cert Sample";
Request.Method = "GET";
HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();

答案 3 :(得分:6)

连接到需要用户代理的GitHub时遇到了同样的问题。因此,提供此证书而不是生成证书就足够了

var client = new HttpClient();

client.BaseAddress = new Uri("https://api.github.com");
client.DefaultRequestHeaders.Add(
    "Authorization",
    "token 123456789307d8c1d138ddb0848ede028ed30567");
client.DefaultRequestHeaders.Accept.Add(
    new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add(
    "User-Agent",
    "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36");

答案 4 :(得分:5)

连接到https时我也遇到了此错误,我在HttpClient httpClient = new HttpClient();之前添加了此行并成功连接:

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

我从This AnswerAnother Similar Anwser了解到这一点,评论中提及:

  

这是一个在开发中很有用的黑客,所以在它周围添加一个#if DEBUG #endif语句是你应该做的最少的事情,让它更安全并阻止它在生产中结束

此外,我没有尝试Another Answer中使用new X509Certificate()new X509Certificate2()制作证书的方法,我不确定只需按new()创建工作与否。

编辑:一些参考文献:

Create a Self-Signed Server Certificate in IIS 7

Import and Export SSL Certificates in IIS 7

Convert .pfx to .cer

Best practices for using ServerCertificateValidationCallback

我发现Thumbprint的值等于x509certificate.GetCertHashString()

Retrieve the Thumbprint of a Certificate

答案 5 :(得分:3)

只需在URI中指定HTTPS即可。

httpClient.BaseAddress = new Uri("https://foobar.com/");

如果请求适用于HTTP但使用HTTPS失败,那么这肯定是证书问题。确保调用者信任证书颁发者并且证书未过期。检查的一种快速简便的方法是尝试在浏览器中进行查询。

您还可能需要检查服务器(如果是您的和/或您可以),将其设置为正确提供HTTPS请求。

答案 6 :(得分:1)

我也得到了错误:

  

基础连接已关闭:无法建立信任   SSL / TLS安全通道的关系。

... Xamarin Forms Android 目标应用程序试图从API提供商处请求 TLS 1.3。

的资源

解决方案是更新项目配置以换掉Xamarin&#34;托管&#34; (.NET)http客户端(从Xamarin Forms v2.5开始,它不支持TLS 1.3),而是使用android本机客户端。

这是视觉工作室中的一个简单项目切换。见下面的截图。

  • 项目属性
  • Android选项
  • 高级
  • 列表项
  • 更改&#34; HttpClient实施&#34;到&#34; Android&#34;
  • 将SSL / TLS实施更改为&#34; Native TLS 1.2 +&#34;

enter image description here

答案 7 :(得分:0)

您可以尝试使用 ModernHttpClient Nuget包:下载包后,您可以像这样实现它:

 var handler = new ModernHttpClient.NativeMessageHandler()
 {
     UseProxy = true,
 };


 handler.ClientCertificateOptions = ClientCertificateOption.Automatic;
 handler.PreAuthenticate = true;
 HttpClient client = new HttpClient(handler);

答案 8 :(得分:0)

将以下声明添加到您的课程中:

public const SslProtocols _Tls12 = (SslProtocols)0x00000C00;
public const SecurityProtocolType Tls12 = (SecurityProtocolType)_Tls12;

之后:

var client = new HttpClient();

并且:

ServicePointManager.SecurityProtocol = Tls12;
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 /*| SecurityProtocolType.Tls */| Tls12;

开心吗? :)

答案 9 :(得分:0)

HttpClientHandler级别有一个非全局设置:

var handler = new HttpClientHandler()
{
    SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
};

var client = new HttpClient(handler);

因此启用了最新的TLS版本。

请注意,默认值SslProtocols.Default实际上是SslProtocols.Ssl3 | SslProtocols.Tls(已检查.Net Core 2.1和.Net Framework 4.6.1)。

答案 10 :(得分:0)

我同意felickz,但我也想添加一个示例来阐明c#中的用法。我在Windows服务中使用SSL,如下所示。

    var certificatePath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "bin");
    gateway = new GatewayService();
    gateway.PreAuthenticate = true;


    X509Certificate2 cert = new X509Certificate2(certificatePath + @"\Attached\my_certificate.pfx","certificate_password");
    gateway.ClientCertificates.Add(cert);

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
    gateway.UserAgent = Guid.NewGuid().ToString();
    gateway.Timeout = int.MaxValue;

如果要在Web应用程序中使用它,我只是在像这样更改代理端的实现:

public partial class GatewayService : System.Web.Services.Protocols.SoapHttpClientProtocol // to => Microsoft.Web.Services2.WebServicesClientProtocol

答案 11 :(得分:-2)

我遇到了这个问题,就我而言,解决方案非常简单:用管理员权限打开Visual Studio。我尝试了上述所有解决方案,但直到执行此操作,它才起作用。希望它可以节省一些宝贵的时间。

答案 12 :(得分:-4)

错误:

  

基础连接已关闭:无法建立信任   SSL / TLS安全通道的关系。

我认为您需要无条件接受以下代码

的证书
ServicePointManager.ServerCertificateValidationCallback += 
    (sender, cert, chain, sslPolicyErrors) => true;

Oppositional在对问题.NET client connecting to ssl Web API的回答中写道。