我正在开发一个需要连接到https站点的项目。每次连接时,我的代码都会引发异常,因为该站点的证书来自不受信任的站点。有没有一种方法可以绕过.net core http中的证书检查?
我从.NET的早期版本中看到了此代码。我想我只需要这样的东西。
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
Answers:
.Net Core不支持ServicePointManager.ServerCertificateValidationCallback。
当前的情况是它将是 即将到来的4.1。* System.Net.Http合约(HttpClient)的新ServerCertificateCustomValidationCallback方法。.NET Core团队现在正在最终确定4.1合同。您可以在github上的此处阅读有关内容
您可以直接在CoreFx或MYGET提要中使用源代码来试用System.Net.Http 4.1的预发布版本:https ://dotnet.myget.org/gallery/dotnet-core
Github上的当前WinHttpHandler.ServerCertificateCustomValidationCallback定义
更新:
如下所述,并非所有实现都支持此回调(即,像iOS这样的平台)。如文档所述,在这种情况下,您可以显式设置验证器:
handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
NET Core 2.2、3.0和3.1也适用
旧答案,可以控制,但可能会抛出PlatformNotSupportedException
:
您可以使用这样的匿名回调函数覆盖HTTP调用上的SSL证书检查
using (var httpClientHandler = new HttpClientHandler())
{
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
using (var client = new HttpClient(httpClientHandler))
{
// Make your request...
}
}
另外,我建议HttpClient
对它使用工厂模式,因为它是一个共享对象,可能不会立即被丢弃,因此连接将保持打开状态。
HttpClient
名为的属性DangerousAcceptAnyServerCertificateValidator
,该属性提供了一种在MacOSX上实现此功能的方法。更多信息在这里-github.com/dotnet/corefx/pull/19908
factory pattern
的HttpClient
?
GetHttpClient
方法将返回配置 的工厂,并在-block中HttpClient
使用它using
。
我用这个解决:
启动文件
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient("HttpClientWithSSLUntrusted").ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
ClientCertificateOptions = ClientCertificateOption.Manual,
ServerCertificateCustomValidationCallback =
(httpRequestMessage, cert, cetChain, policyErrors) =>
{
return true;
}
});
YourService.cs
public UserService(IHttpClientFactory clientFactory, IOptions<AppSettings> appSettings)
{
_appSettings = appSettings.Value;
_clientFactory = clientFactory;
}
var request = new HttpRequestMessage(...
var client = _clientFactory.CreateClient("HttpClientWithSSLUntrusted");
HttpResponseMessage response = await client.SendAsync(request);
来到这里寻找相同问题的答案,但是我将WCF用于NET Core。如果您在同一条船上,请使用:
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.None,
RevocationMode = X509RevocationMode.NoCheck
};
在.NetCore中,您可以在services configure方法中添加以下代码段,我添加了一项检查以确保仅在开发环境中通过SSL证书。
services.AddHttpClient("HttpClientName", client => {
// code to configure headers etc..
}).ConfigurePrimaryHttpMessageHandler(() => {
var handler = new HttpClientHandler();
if (hostingEnvironment.IsDevelopment())
{
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
}
return handler;
});
在.NET Core 2.2和Docker Linux容器上使用自签名证书和客户端证书auth时,我遇到了相同的问题。在我的dev Windows机器上,一切正常,但是在Docker中,我遇到了这样的错误:
System.Security.Authentication.AuthenticationException:根据验证过程,远程证书无效
幸运的是,证书是使用链生成的。当然,您始终可以忽略此解决方案,而使用上述解决方案。
所以这是我的解决方案:
我使用Chrome以P7B格式保存了证书。
使用以下命令将证书转换为PEM格式:
openssl pkcs7 -inform DER -outform PEM -in <cert>.p7b -print_certs > ca_bundle.crt
打开ca_bundle.crt文件并删除所有主题记录,保留一个干净的文件。下面的例子:
-----BEGIN CERTIFICATE-----
_BASE64 DATA_
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
_BASE64 DATA_
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
_BASE64 DATA_
-----END CERTIFICATE-----
# Update system and install curl and ca-certificates
RUN apt-get update && apt-get install -y curl && apt-get install -y ca-certificates
# Copy your bundle file to the system trusted storage
COPY ./ca_bundle.crt /usr/local/share/ca-certificates/ca_bundle.crt
# During docker build, after this line you will get such output: 1 added, 0 removed; done.
RUN update-ca-certificates
var address = new EndpointAddress("https://serviceUrl");
var binding = new BasicHttpsBinding
{
CloseTimeout = new TimeSpan(0, 1, 0),
OpenTimeout = new TimeSpan(0, 1, 0),
ReceiveTimeout = new TimeSpan(0, 1, 0),
SendTimeout = new TimeSpan(0, 1, 0),
MaxBufferPoolSize = 524288,
MaxBufferSize = 65536,
MaxReceivedMessageSize = 65536,
TextEncoding = Encoding.UTF8,
TransferMode = TransferMode.Buffered,
UseDefaultWebProxy = true,
AllowCookies = false,
BypassProxyOnLocal = false,
ReaderQuotas = XmlDictionaryReaderQuotas.Max,
Security =
{
Mode = BasicHttpsSecurityMode.Transport,
Transport = new HttpTransportSecurity
{
ClientCredentialType = HttpClientCredentialType.Certificate,
ProxyCredentialType = HttpProxyCredentialType.None
}
}
};
var client = new MyWSClient(binding, address);
client.ClientCredentials.ClientCertificate.Certificate = GetClientCertificate("clientCert.pfx", "passwordForClientCert");
// Client certs must be installed
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication
{
CertificateValidationMode = X509CertificateValidationMode.ChainTrust,
TrustedStoreLocation = StoreLocation.LocalMachine,
RevocationMode = X509RevocationMode.NoCheck
};
GetClientCertificate方法:
private static X509Certificate2 GetClientCertificate(string clientCertName, string password)
{
//Create X509Certificate2 object from .pfx file
byte[] rawData = null;
using (var f = new FileStream(Path.Combine(AppContext.BaseDirectory, clientCertName), FileMode.Open, FileAccess.Read))
{
var size = (int)f.Length;
var rawData = new byte[size];
f.Read(rawData, 0, size);
f.Close();
}
return new X509Certificate2(rawData, password);
}
首先,请勿在生产中使用它
如果您使用的是AddHttpClient中间件,则将非常有用。我认为这是出于发展目的而不是生产目的。在创建有效证书之前,您可以使用此功能。
Func<HttpMessageHandler> configureHandler = () =>
{
var bypassCertValidation = Configuration.GetValue<bool>("BypassRemoteCertificateValidation");
var handler = new HttpClientHandler();
//!DO NOT DO IT IN PRODUCTION!! GO AND CREATE VALID CERTIFICATE!
if (bypassCertValidation)
{
handler.ServerCertificateCustomValidationCallback = (httpRequestMessage, x509Certificate2, x509Chain, sslPolicyErrors) =>
{
return true;
};
}
return handler;
};
并像
services.AddHttpClient<IMyClient, MyClient>(x => { x.BaseAddress = new Uri("https://localhost:5005"); })
.ConfigurePrimaryHttpMessageHandler(configureHandler);
允许所有证书非常强大,但这也很危险。如果您只想允许有效的证书加上某些证书,可以这样进行。
using (var httpClientHandler = new HttpClientHandler())
{
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) => {
if (sslPolicyErrors == SslPolicyErrors.None)
{
return true; //Is valid
}
if (cert.GetCertHashString() == "99E92D8447AEF30483B1D7527812C9B7B3A915A7")
{
return true;
}
return false;
};
using (var httpClient = new HttpClient(httpClientHandler))
{
var httpResponse = httpClient.GetAsync("https://example.com").Result;
}
}
原始资料: