Visual Studio中SOAP客户端使用X509证书时SSL/TLS信任关系建立失败问题求助
解决SOAP客户端使用X509Certificate时的HTTPS与证书信任问题
先梳理下你遇到的两个问题:
第一个
httpURI错误是因为你用了CertificateOverTransport认证模式——这个模式要求传输层必须是HTTPS(因为证书要通过加密通道传递),所以把URI改成https是完全正确的操作,这一步没问题。第二个SSL信任问题,虽然你加了
ServerCertificateValidationCallback但没生效,大概率是WCF的证书验证逻辑和ServicePointManager的全局设置不兼容,或者回调的实现/时机有问题。下面给你几个可行的解决办法,按从简单到彻底的顺序来:
办法1:检查并修复ServerCertificateValidationCallback的实现与注册时机
首先确认你的AlwaysGoodCertificate函数是不是真的返回true,并且是在创建SOAP客户端实例之前注册的:
// 必须在客户端实例化前注册 ServicePointManager.ServerCertificateValidationCallback += AlwaysGoodCertificate; // 回调函数的正确实现 private static bool AlwaysGoodCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors) { // 忽略所有证书错误,仅测试环境用! return true; } // 然后再创建客户端 var soapClient = new YourSoapServiceClient();
如果注册时机不对(比如在客户端创建后才加回调),WCF已经初始化了连接,回调就不会生效。
办法2:给WCF客户端添加自定义证书验证行为
WCF有时候会绕过ServicePointManager的全局设置,这时候可以通过自定义EndpointBehavior来强制关闭证书验证:
首先创建一个自定义行为类:
public class TrustAllCertificatesBehavior : IEndpointBehavior { public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { var creds = new ServiceCredentials(); creds.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None; creds.ServiceCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck; bindingParameters.Add(creds); } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } public void Validate(ServiceEndpoint endpoint) { } }
然后在创建客户端后添加这个行为:
var client = new YourSoapServiceClient(); client.Endpoint.Behaviors.Add(new TrustAllCertificatesBehavior());
这个方法直接针对WCF的证书验证逻辑,比全局回调更可靠。
办法3:把自签名证书导入系统受信任根证书库
如果测试环境长期使用这个自签名证书,最彻底的办法是让系统信任它,这样不需要改任何代码:
- 从服务端导出自签名证书(格式选
.cer) - 打开Windows的MMC控制台,添加「证书」管理单元,选择「计算机账户」
- 展开「受信任的根证书颁发机构」→「证书」,右键选择「所有任务」→「导入」
- 按照向导导入刚才的
.cer文件,完成后系统就会信任这个证书,WCF的SSL错误也会消失
办法4:调整WCF配置文件的客户端证书验证设置
如果你更喜欢用配置文件而不是代码,可以在客户端的app.config/web.config里添加客户端行为,关闭服务端证书验证:
<system.serviceModel> <behaviors> <endpointBehaviors> <behavior name="TrustAllBehavior"> <clientCredentials> <serviceCertificate> <!-- 关闭证书验证和吊销检查 --> <authentication certificateValidationMode="None" revocationMode="NoCheck" /> </serviceCertificate> </clientCredentials> </behavior> </endpointBehaviors> </behaviors> <client> <!-- 在你的客户端endpoint里引用这个behavior --> <endpoint address="https://services.pl/your-service" binding="customBinding" bindingConfiguration="myCustomBindingConfig" contract="YourServiceContract" behaviorConfiguration="TrustAllBehavior" /> </client> </system.serviceModel>
注意:所有关闭证书验证的方法仅适合测试环境,生产环境必须使用由可信CA颁发的证书,并且开启严格的证书验证!
内容的提问来源于stack exchange,提问作者ITMemberAHE




