使用 HttpClient 的“远程证书根据验证程序无效”
Posted
技术标签:
【中文标题】使用 HttpClient 的“远程证书根据验证程序无效”【英文标题】:"The remote certificate is invalid according to the validation procedure" using HttpClient 【发布时间】:2016-03-25 02:10:53 【问题描述】:无法解决证书验证问题。
有一个 Web API 服务器,它使用 HTTPS 来处理请求。服务器的证书有这样的认证路径:RCA (root) -> ICA (intermediate) -> Web API server。 RCA、ICA 和 Web API 服务器是同一个 Active Directory 域的成员。
客户端应用(桌面、电脑加入同一个域)使用HttpClient
与服务器通信,支持两种场景:
这两种情况都使用基本身份验证。 RCA 和 ICA 证书分别放置在本地计算机帐户的“受信任的根证书颁发机构”和“中间证书颁发机构”中。 RCA 证书是自签名的。
现在,当客户端连接到公司网络时,证书验证按预期工作,用户可以与 Web API“对话”。
当客户端断开连接(只有 Internet 连接可用)时,证书验证失败并显示 AuthenticationException
(“根据验证过程,远程证书无效”)。
我不想完全关闭证书验证,但只需要一种方法告诉验证系统,这个特定的证书是有效的。 此外,客户端应用程序使用 SignalR,默认情况下使用它自己的传输。因此,this 和 this 不是选项。
为什么将 RCA 和 ICA 证书放入“受信任...”和“中级...”文件夹没有帮助?
有什么解决办法吗?
【问题讨论】:
也许当您从 Internet 连接时,Uri 主机名和证书主题之间不再匹配? 两种方案都使用相同的连接字符串:“host.domain.zone”。证书科目有:1)RCA:“RCA, domain, zone”; 2)ICA:“ICA1,域,区域”; 3) Web 服务器:“HOST.domain.zone”。我不知道,不同的主题格式是否起作用...... 也许您可以发布您网站的公共 URL 以便我们查看? 另外,如果我尝试通过 IE 连接 Web API,我会收到以下消息:“此网站提供的安全证书是为不同网站的地址颁发的”。 “该网站提供的安全证书是针对不同网站的地址签发的”基本上就是我在第一条评论中所说的。 【参考方案1】:您遇到的问题是因为证书提供的主题 CN 与 Uri 中的主机名不匹配。
确保绑定到主机公共 IP 地址的证书确实具有与您用于访问资源的主机名匹配的 CN。
要轻松验证,请在浏览器中打开 URL 并查看证书。 Issued to 字段应包含 FQDN 并与 Uri 中的主机名部分匹配。在你的情况下,它没有。
【讨论】:
【参考方案2】:在程序主体上插入这段代码:
static void Main(string[] args)
ServicePointManager.ServerCertificateValidationCallback =
delegate (object sender, X509Certificate certificate, X509Chain
chain, SslPolicyErrors sslPolicyErrors)
return true;
;
....
【讨论】:
当我需要测试提供自签名开发证书的 api 时,这对我在开发环境中运行时有用。 这实际上完全禁用了证书验证。强烈不推荐。 另外,使用客户端证书时不会触发回调。见:github.com/dotnet/corefx/issues/17226 这对于在单元或 SIT 测试 Web 服务时使用自签名证书非常方便。需要注意的是,它并没有禁用身份验证,它只是禁用了证书的客户端验证。 显然不推荐用于生产代码,但非常推荐用于概念证明或单元测试。必须为特定证书编写解决方法将需要构建该基础设施,然后无论如何这些基础设施将被完全丢弃在生产代码中。所以我相信这个解决方案对于这种特殊情况是有好处的。【参考方案3】:不幸的是,@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 不显示控制台输出。因此,我启用了调试日志记录到文件(不在 sn-p 中)
【讨论】:
以上是关于使用 HttpClient 的“远程证书根据验证程序无效”的主要内容,如果未能解决你的问题,请参考以下文章