调用ServerCertificateValidationCallback之前出现远程证书无效错误
本文关键字:证书 错误 无效 程证书 ServerCertificateValidationCallback 调用 | 更新日期: 2023-09-27 18:27:18
我在尝试连接到SOAP 1.1服务器时遇到异常。我从另一个组织收到了WSDL,并使用.net将其作为服务参考纳入我的项目中。
要求我们使用包含MTOM附件和HTTPgzip压缩。它还要求Web服务安全性(WS-Security)版本1.0(使用OASIS标准)使用X.509身份验证框架实现端到端安全。
我在c#中使用4.5.2.Net框架。
以下是我的app.config的相关部分,其中对潜在的敏感信息进行了编辑:
<basicHttpBinding>
<binding name="customHttpBinding" allowCookies="true" messageEncoding="Mtom">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Certificate" />
<message clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>
[snip]
<client>
<endpoint address="YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"
binding="basicHttpBinding" bindingConfiguration="customHttpBinding"
contract="SERVICENAME.BulkRequestTransmitterPortType"
name="BulkRequestTransmitterPort">
<identity>
<certificateReference storeLocation="CurrentUser" x509FindType="FindBySerialNumber"
findValue="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" />
</identity>
</endpoint>
</client>
X是我的密钥的序列号(确认在我的计算机存储中),Y是端点
以下是我创建和调用服务的部分(X是相同的证书):
var transmitter = new BulkRequestTransmitterPortTypeClient();
transmitter.ClientCredentials?.ClientCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.My,
X509FindType.FindBySerialNumber,
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
var response = transmitter.BulkRequestTransmitter(
securityHeader,
security,
ref businessHeader,
transmitterManifestReqDtl,
transmitterType);
它在最后一行爆炸,并出现以下错误:
ex {"Could not establish trust relationship for the SSL/TLS secure channel with authority 'YYYYYYYYYYYY'."} System.Exception {System.ServiceModel.Security.SecurityNegotiationException}
+InnerException {"The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."} System.Exception {System.Net.WebException}
+InnerException {"The remote certificate is invalid according to the validation procedure."} System.Exception {System.Security.Authentication.AuthenticationException}
每当我进行搜索时,我都会发现两个建议,第一个是确保服务器证书在我的可信存储中,并且第三方授权机构是可信的。我已经验证了这两个都在我本地计算机的存储中并且是可信的。第二个也是最常见的建议是重写ServicePointManager.ServerCertificateValidationCallback,返回true如下:
ServicePointManager.ServerCertificateValidationCallback = delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
};
尽管我很犹豫是否要尝试这个(即使在开发环境中我也不喜欢使用糟糕的做法),但我认为在调试中使用它是值得的。遗憾的是,断点从未命中。我在服务器CertificateValidationCallback关闭之前收到错误。
我现在不知所措。我不确定我做错了什么,因为我对配置所做的每一次更改都会在更早的时候产生错误,所以我认为我走在了正确的道路上,但不确定验证过程失败的原因以及如何解决。我很感激能提供的任何帮助。
这是因为有问题的服务器没有使用证书。如果您通知.net希望从服务器获得一个证书,那么它将在到达ServerCertificateValidationCallback之前失败,并显示此错误消息。
不幸的是,我不是心灵感应者,可以判断出是什么导致了你的问题。不过,我可以提供一些见解。
仅出于调试目的,您可以获得连接失败的确切原因。使用此回调委托:
ServicePointManager.ServerCertificateValidationCallback = delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
};
并在委托调用上设置断点。激发时,请使用调试器检查chain
参数。ChainElements
属性包含X509ChainElement对象的集合。每个对象都与链中的特定证书、链中每个证书的状态和证书状态(通过ChainElementStatus)相关联。请注意,链元素的状态是累积的,这意味着错误从最顶层的证书向下传播。换句话说,ChainElementStatus
成员将包含与特定ChainElement
相关联的错误加上来自上层的组合错误。
一旦发现并解决了问题,请将该代表除名。
另一个选项是将远程服务器的证书文件(只有公共证书)传递给certutil:
certutil -verify -urlfetch path'remoteserver.cer
输出可能有点复杂,但它将提供额外的信息,而X509Chain调试无法获得这些信息。最常见的问题(在不受信任的根之后)是RevocationOffline
,certutil将显示吊销检查的详细信息,包括每个URL的可用性和有效性。