SSL连接无法建立。

109

我在我的ASP.NET Core应用程序中使用第三方库(Splunk c# SDK),尝试通过此SDK连接到我的本地Splunk服务,但遇到以下异常:

System.Net.Http.HttpRequestException:无法建立SSL连接,请参见内部异常。

而内部异常信息如下:

根据验证过程,远程证书无效。

该SDK在底层使用HTTP客户端,但我无法访问此对象以配置HttpClientHandler。

我在谷歌上搜索的所有结果都使用ServicePointManager来绕过SSL验证,但这种解决方法在Asp.Net core中不起作用。

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

有没有办法在 asp.Net Core 中绕过此验证?


3
你能否在你的机器上注册本地主机服务的证书,使其有效? - ProgrammingLlama
1
@John 我该如何注册?你能详细说明一下吗? - MVafa
1
你的本地服务器也是ASP.NET的吗?还是其他的? - ProgrammingLlama
1
@John 不是这样的。服务器是Splunk Enterprise,我只是下载并安装它,在本地主机上托管服务:8089。 - MVafa
1
你需要找到一种方法来导出它正在使用的SSL证书,或者使用自己的自签名证书。然后,你可以通过certmgr.msc将其添加到Windows中。 - ProgrammingLlama
1
对于Asp.Net Core中的HttpClient,您可以尝试使用ServerCertificateCustomValidationCallback,参考bypass invalid SSL certificate in .net core,但似乎无法通过HttpClientHandler传递,您可以检查一下Splunk c# SDK是否公开了此功能。 - Edward
14个回答

197

是的,您可以使用以下代码绕过证书...

HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };

// Pass the handler to httpclient(from you are calling api)
HttpClient client = new HttpClient(clientHandler);

39
请注意,这个解决方案只是从你的代码中移除了所有证书验证,因此存在安全问题! - Daniël Tulp
1
在MVC项目中,这应该放在哪里? - Bbb
1
一个在我们这种情况下工作的更安全的解决方案是:clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => cert.Verify() - noontz
1
@noontz 在我的.NET 7应用程序中,使用cert.Verify()方法并没有起作用,而使用return true却在我的开发环境中完美运行。 - undefined

57

当我在我的开发者计算机上使用身份验证服务器(.net core)和 Web API(.net core)时,我意识到我需要信任本地主机的 SSL 证书。以下命令可以完成此操作:

dotnet dev-certs https --trust

2
哇,只用一个答案就得到了超过300分的成绩 :O - Ravi Makwana

23

如果您正在添加一个IHttpClient并通过 DI 进行注入,则可以在 Startup.cs 类中添加配置。

public void ConfigureServices(IServiceCollection services)
        {
services.AddHttpClient("yourServerName").ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler
            {
               ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; }

            });
}

然后从您的依赖注入类中调用它。

public class MyServiceClass 
    {
private readonly IHttpClientFactory _clientFactory;
public MyServiceClass (IConfiguration configuration, IHttpClientFactory clientFactory)
        {
            _clientFactory = clientFactory;
} 

 public async Task<int> DoSomething()
{
var url = "yoururl.com";
var client = _clientFactory.CreateClient("yourServerName");
var result = await client.GetAsync(url);
}

1
你的代码解决了我的问题,现在在 .Net 5 Worker 中它完美地工作了。非常感谢你。 - agileDev
1
谢谢。你的第一段代码解决了我这个情况下确切的SSL问题。谢谢。 - suma
1
谢谢。在 .Net Core 6 中解决了我的问题。我已将该代码添加到 Program.cs 文件中。 - Mahdi Abyaznezhad
3
当然,这样可以解决问题;它禁用了SSL验证 - Zimano

13

安装 .NET Core SDK 会将 ASP.NET Core HTTPS 开发证书安装到本地用户证书存储中。证书已经安装,但是它不受信任。要信任该证书,请执行一次性步骤运行 dotnet dev-certs 工具:

dotnet dev-certs https --trust

欲了解更多信息,请访问此链接


1
SDK卸载后如何删除开发证书? - Aamir
2
这个答案解决了我在生产服务器上的问题!谢谢 :) - Iman Nemati

9

2
ServicePointManager 类现在已经过时。 https://learn.microsoft.com/zh-cn/dotnet/api/system.net.servicepointmanager?view=net-6.0 - N_E

8
这对我很有用,
通过提供自定义的 HttpClientHandler 创建一个 Splunk.Client.Context,该处理程序将绕过SSL 无效证书错误。
HttpClientHandler handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };

// Create Context 
Context context = new Context(Scheme.Https, "localhost", 8089, default(TimeSpan), handler);

// Create Service
service = new Service(context);

5
您之所以收到此错误,是因为您的应用程序无法验证连接的证书,特别是在使用创建会话/登录令牌的API时很常见。您可以像上面展示的那样以一种危险的方式绕过它,但显然这不是一个好的解决方案,除非您只是在测试。
最好和最简单的解决方案是使用“modernhttpclient-updated” Nuget包,其代码在this GitHub repo中共享,那里还有很多文档。
一旦您添加了Nuget包,请将NativeMessageHandler传递给HttpClient(),如下所示并构建: var httpClient = new HttpClient(new NativeMessageHandler()); 现在,您会注意到已经摆脱了该错误,并且会收到另一条错误消息,例如:Certificate pinning failure: chain error. ---> Javax.Net.Ssl.SSLPeerUnverifiedException: Hostname abcdef.ghij.kl.mn not verified: certificate: sha256/9+L...C4Dw= 为了消除这个新的错误消息,您需要将错误中的主机名和证书密钥添加到 Pin 中,并将其添加到 NativeMessageHandler 的 TLSConfig 中,如下所示:
var pin = new Pin();
pin.Hostname = "abcdef.ghij.kl.mn";
pin.PublicKeys = new string[] { "sha256/9+L...C4Dw=" };
var config = new TLSConfig();
config.Pins = new List<Pin>();
config.Pins.Add(pin);
httpClient = new HttpClient(new NativeMessageHandler(true, config)

请记住,您的其他(非令牌生成)API调用可能不实现证书固定,因此可能不需要此功能,并且通常它们可能使用不同的主机名。在这种情况下,您也需要将它们注册为锁定,或者只需为它们使用不同的HttpClient!

2
我在这个服务器上使用HttpWebRequest已经有一段时间了,没有任何问题,但是最近出现了远程验证错误,尽管应用程序没有验证过程,只是一个HttpWebRequest。您是否意味着上述库提供比HttpWebRequest更多的信息? - Dan Chase
1
嘿@DanChase,你更新了后端或前端框架版本吗?这可能是你看到它的原因。 另外,似乎你正在使用HTTPWebRequest而不是HTTPclient。我没有使用过前者,而且问题也使用了httpclient。 - Saamer
2
结果证明是过期的 Let's Encrypt 根证书引起了这个问题,必须从机器上删除。我永远不会想到这一点,但愿有一些诊断工具可以帮助解决这个问题。我在 .net mono 上拉取了源代码并查看了验证,但它并没有真正帮助,因为它似乎只是沿着链条向上走。删除过期的根证书是一个绝望的尝试,但它奏效了。我甚至没有看到该证书在站点证书的链中。只有通过 FQDN/等连接到自身时出现问题,而不是连接到雅虎或谷歌等网站。可怕的是,现在每个人都在禁用验证。 - Dan Chase

4

我必须关闭我的VPN才能解决这个错误


1

这很可能是由于代理配置不正确引起的。

不幸的是,一些新的Windows工作站的设置是错误的。

通过在Windows命令提示符中运行以下脚本来检查您的系统环境变量。

如果您的代理值已配置,但没有任何NO_PROXY设置,那么在尝试访问内部服务时会遇到问题。

最终,我建议取消设置HTTP_PROXY和HTTPS_PROXY变量,除非您知道它们的作用以及需要它们的原因。

同样重要的是,检查no_proxy的值并与您的同事进行比较,看看是否有任何差异,有时一个点“.”可以产生差异。


1

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