Answers:
使用Windows 8.1,您现在可以信任无效的SSL证书。您必须使用Windows.Web.HttpClient,或者如果您想使用System.Net.Http.HttpClient,则可以使用我编写的消息处理程序适配器:http : //www.nuget.org/packages/WinRtHttpClientHandler
文档在GitHub上:https : //github.com/onovotny/WinRtHttpClientHandler
一种快速而肮脏的解决方案是使用ServicePointManager.ServerCertificateValidationCallback
委托。这使您可以提供自己的证书验证。验证将在整个应用程序域中全局应用。
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
我主要在需要针对正在托管的终结点计算机上运行并尝试使用WCF客户端或WCF客户端进行测试的情况下,将其用于单元测试HttpClient
。
对于生产代码,您可能需要更细粒度的控制,并且最好使用WebRequestHandler
和及其ServerCertificateValidationCallback
委托属性(请参见下面的dtb的答案)。或使用ctacke 回答HttpClientHandler
。我现在更喜欢使用这两个方法中的任何一个,即使在进行集成测试时,也比过去更喜欢使用它,除非找不到其他钩子。
看一下WebRequestHandler类及其ServerCertificateValidationCallback属性:
using (var handler = new WebRequestHandler())
{
handler.ServerCertificateValidationCallback = ...
using (var client = new HttpClient(handler))
{
...
}
}
derived class
?
HttpClientHandler
?
如果您尝试在.NET Standard库中执行此操作,则这是一个简单的解决方案,其中存在仅返回true
处理程序的所有风险。我把安全交给你。
var handler = new HttpClientHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ServerCertificateCustomValidationCallback =
(httpRequestMessage, cert, cetChain, policyErrors) =>
{
return true;
};
var client = new HttpClient(handler);
或者,您可以在名称空间中使用HttpClientWindows.Web.Http
:
var filter = new HttpBaseProtocolFilter();
#if DEBUG
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Expired);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
#endif
using (var httpClient = new HttpClient(filter)) {
...
}
System.Net.Http
,System.Web
并Windows.Web.Http
在一起呢?
此处的大多数答案建议使用典型模式:
using (var httpClient = new HttpClient())
{
// do something
}
由于IDisposable接口。请不要!
Microsoft告诉您原因:
在这里您可以找到详细的分析幕后情况:https: //aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
关于您的SSL问题,并基于https://docs.microsoft.com/zh-CN/azure/architecture/antipatterns/improper-instantiation/#how-to-fix-the-problem
这是您的模式:
class HttpInterface
{
// https://docs.microsoft.com/en-us/azure/architecture/antipatterns/improper-instantiation/#how-to-fix-the-problem
// https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient#remarks
private static readonly HttpClient client;
// static initialize
static HttpInterface()
{
// choose one of these depending on your framework
// HttpClientHandler is an HttpMessageHandler with a common set of properties
var handler = new HttpClientHandler();
{
ServerCertificateCustomValidationCallback = delegate { return true; },
};
// derives from HttpClientHandler but adds properties that generally only are available on full .NET
var handler = new WebRequestHandler()
{
ServerCertificateValidationCallback = delegate { return true; },
ServerCertificateCustomValidationCallback = delegate { return true; },
};
client = new HttpClient(handler);
}
.....
// in your code use the static client to do your stuff
var jsonEncoded = new StringContent(someJsonString, Encoding.UTF8, "application/json");
// here in sync
using (HttpResponseMessage resultMsg = client.PostAsync(someRequestUrl, jsonEncoded).Result)
{
using (HttpContent respContent = resultMsg.Content)
{
return respContent.ReadAsStringAsync().Result;
}
}
}
如果这是Windows运行时应用程序,则必须将自签名证书添加到项目中,并在appxmanifest中引用它。
该文档位于此处:http : //msdn.microsoft.com/zh-cn/library/windows/apps/hh465031.aspx
如果它来自不受信任的CA(例如计算机本身不信任的私有CA),则也是一样-您需要获取CA的公共证书,将其作为内容添加到应用程序中,然后将其添加到清单中。
完成后,应用程序会将其视为正确签名的证书。
我在这个Kubernetes客户端中使用X509VerificationFlags.AllowUnknownCertificateAuthority信任自签名自签名根证书的示例。我稍微修改了他们的示例,以使用我们自己的PEM编码的根证书。希望这对某人有帮助。
namespace Utils
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
/// <summary>
/// Verifies that specific self signed root certificates are trusted.
/// </summary>
public class HttpClientHandler : System.Net.Http.HttpClientHandler
{
/// <summary>
/// Initializes a new instance of the <see cref="HttpClientHandler"/> class.
/// </summary>
/// <param name="pemRootCerts">The PEM encoded root certificates to trust.</param>
public HttpClientHandler(IEnumerable<string> pemRootCerts)
{
foreach (var pemRootCert in pemRootCerts)
{
var text = pemRootCert.Trim();
text = text.Replace("-----BEGIN CERTIFICATE-----", string.Empty);
text = text.Replace("-----END CERTIFICATE-----", string.Empty);
this.rootCerts.Add(new X509Certificate2(Convert.FromBase64String(text)));
}
this.ServerCertificateCustomValidationCallback = this.VerifyServerCertificate;
}
private bool VerifyServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
// If the certificate is a valid, signed certificate, return true.
if (sslPolicyErrors == SslPolicyErrors.None)
{
return true;
}
// If there are errors in the certificate chain, look at each error to determine the cause.
if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) != 0)
{
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
// add all your extra certificate chain
foreach (var rootCert in this.rootCerts)
{
chain.ChainPolicy.ExtraStore.Add(rootCert);
}
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
var isValid = chain.Build((X509Certificate2)certificate);
var rootCertActual = chain.ChainElements[chain.ChainElements.Count - 1].Certificate;
var rootCertExpected = this.rootCerts[this.rootCerts.Count - 1];
isValid = isValid && rootCertActual.RawData.SequenceEqual(rootCertExpected.RawData);
return isValid;
}
// In all other cases, return false.
return false;
}
private readonly IList<X509Certificate2> rootCerts = new List<X509Certificate2>();
}
}
我在网上找到了一个效果不错的示例:
首先,您创建一个新的ICertificatePolicy
using System.Security.Cryptography.X509Certificates;
using System.Net;
public class MyPolicy : ICertificatePolicy
{
public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request,
int certificateProblem)
{
//Return True to force the certificate to be accepted.
return true;
}
}
然后只需在发送http请求之前使用它,如下所示:
System.Net.ServicePointManager.CertificatePolicy = new MyPolicy();
http://www.terminally-incoherent.com/blog/2008/05/05/send-a-https-post-request-with-c/
ServicePointManager.CertificatePolicy
不推荐使用:docs.microsoft.com/en-us/dotnet/framework/whats-new/…–