使用HttpClient进行Https调用

193

我一直在使用C#中的HttpClient来进行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 是第一步。

如何在 C# 请求中提供证书和公钥/私钥。


2
你只需指定 new Uri("https://foobar.com/"); 就可以进行 HTTPS 调用。 - felickz
2
我有点困惑。那不是已经可以工作了吗?你收到了错误吗?(编辑:在 OP 将 URI 从 https 更改为 http 之前发布) - Tim
14个回答

0
你可以尝试使用 ModernHttpClient Nuget 包:下载该包后,你可以像这样实现它:
 var handler = new ModernHttpClient.NativeMessageHandler()
 {
     UseProxy = true,
 };


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

很遗憾,这对我没有起作用。解决方法是通过从Xamarin托管的HTTP客户端切换到Android本机HTTP客户端来启用TLS 1.3。请参见下面的回答。 - MSC

0

这里是可在 HTTPS 调用中工作的可工作代码

UriBuilder builder = new UriBuilder("https://yourdomain.com/");
builder.Query = "id=10";                 
//Create a query
HttpClient client = new HttpClient();
System.Net.ServicePointManager.SecurityProtocol = 
SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;                  
client.DefaultRequestHeaders.Add("Authorization", userprofile.Token);                
var result = client.GetAsync(builder.Uri).Result;                                       
using (StreamReader sr = new 
StreamReader(result.Content.ReadAsStreamAsync().Result))
{                       
   responseres = sr.ReadToEnd();
}

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

-5

针对错误:

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

我认为您需要使用以下代码无条件接受证书。

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

正如Oppositional在他对问题.NET客户端连接到ssl Web API的回答中所写的那样。


4
这是绕过证书验证。在生产环境中千万不要这样做。 - John Korsnes
嗯,@JohnKorsnes,如果Abhijeet正在访问一些公共WebAPI服务器,我认为他无能为力。这就是我的情况。 - Nemanja Simović

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接