"The remote certificate is invalid according to the validation procedure" 使用 HttpClient

"The remote certificate is invalid according to the validation procedure" using HttpClient

无法解决证书验证问题。

Web API 服务器使用 HTTPS 处理请求。服务器的证书具有以下证书路径:RCA(根)-> ICA(中级)-> Web API 服务器。 RCA、ICA 和 Web API 服务器是同一 Active Directory 域的成员。

客户端应用程序(桌面,计算机加入同一个域)使用HttpClient与服务器通信并支持两种场景:

两种情况都使用基本身份验证。
RCA 和 ICA 证书分别放在 "Trusted Root Certification Authorities" 和 "Intermediate Certification Authorities" 中,用于本地计算机帐户。 RCA 证书是自签名的。

现在,当客户端连接到公司网络时,证书验证按预期进行,用户可以 "talk" 访问 Web API。

当客户端断开连接时(只有 Internet 连接可用),证书验证失败 AuthenticationException ("The remote certificate is invalid according to the validation procedure")。

我不想完全关闭证书验证,只是需要一种方法来告诉验证系统这个特定证书是有效的。 此外,客户端应用程序使用 SignalR,默认情况下它使用自己的传输。因此,this and this 不是选项。

为什么将 RCA 和 ICA 证书放入 "Trusted..." 和 "Intermediate..." 文件夹没有帮助?

有什么解决方法吗?

您遇到的问题是因为证书提供的主题 CN 与 Uri 中的主机名不匹配。

确保绑定到主机 public IP 地址的证书确实具有与您用来访问资源的主机名相匹配的 CN。

要轻松验证,请在浏览器中打开 Url 并查看证书。 Issued to 字段应包含 FQDN 并匹配 Uri 中的主机名部分。在你的情况下,它不会。

在程序体中插入这段代码:

static void Main(string[] args)   
{
     ServicePointManager.ServerCertificateValidationCallback =
                delegate (object sender, X509Certificate certificate, X509Chain 
     chain, SslPolicyErrors sslPolicyErrors)
                {
                    return true;
                };
     ....
}

不幸的是,@Qosai 的回答对我来说还不够,至少在 SignalR 3.1 客户端中是这样,因为 websocket 部分还验证 SSL 证书。 ClientCertificateOptions 也需要设置为手动。

我找到了 SignalR 贡献者的 post 让我开始工作:

_connection = new HubConnectionBuilder()
            .WithUrl(new Uri(hub_uri), options => {
                options
                    .Cookies
                    .Add(http_helper.loginCookie);

                var handler = new HttpClientHandler
                {
                    ClientCertificateOptions = ClientCertificateOption.Manual,
                    ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => true
                };
                options.HttpMessageHandlerFactory = _ => handler;
                options.WebSocketConfiguration = sockets =>
                {
                    sockets.RemoteCertificateValidationCallback = (sender, certificate, chain, policyErrors) => true;
                };
            })
            .Build();

PS:如果您仍有问题,请查看此 article 以了解如何正确启用日志记录。就我而言,这有点棘手,因为 xUnit 不显示控制台输出。因此我启用了调试日志记录到一个文件(不在代码片段中)