WCF服务中自定义X509CertificateValidator的Validate方法未触发问题排查
问题根源与解决方案
你的自定义X509CertificateValidator.Validate()方法没被调用,核心原因是当前的绑定配置只启用了服务器端的SSL加密,完全没有要求客户端提供证书——服务端根本没触发客户端证书的验证流程,自然不会调用你的自定义验证器。
具体分析
你现在用的SslStreamSecurityBindingElement只是让服务端通过证书提供SSL加密,客户端会验证服务端的证书,但服务端并不会要求客户端提交自己的证书。这种情况下,服务端的ClientCertificate相关配置(包括自定义验证器)根本不会生效,因为没有客户端证书需要验证。
修复步骤
1. 修改绑定配置,要求客户端提供证书
在你的getBinding()方法中,不要直接添加SslStreamSecurityBindingElement,而是直接配置TCP传输绑定元素的SSL设置,开启客户端证书要求:
private static CustomBinding getBinding(bool useCompression, bool useSSL) { BindingElementCollection elements = new BindingElementCollection(); // 消息编码部分保持不变 BinaryMessageEncodingBindingElement binaryMessageEncodingBE = new BinaryMessageEncodingBindingElement(); if (useCompression) { GZipMessageEncodingBindingElement gZipMessageEncodingBE = new GZipMessageEncodingBindingElement(binaryMessageEncodingBE); elements.Add(gZipMessageEncodingBE); } else { elements.Add(binaryMessageEncodingBE); } // TCP传输绑定元素配置 TcpTransportBindingElement tcpTransportBE = new TcpTransportBindingElement(); tcpTransportBE.MaxReceivedMessageSize = 1048576; tcpTransportBE.ListenBacklog = 1000; tcpTransportBE.MaxPendingConnections = 1000; tcpTransportBE.MaxPendingAccepts = 1000; tcpTransportBE.ConnectionPoolSettings.MaxOutboundConnectionsPerEndpoint = 1000; // 配置SSL并要求客户端证书 if (useSSL) { tcpTransportBE.SslSettings = new TcpSslSettings { Enabled = true, SslProtocols = SslProtocols.Tls11, // 关键:开启客户端证书要求,服务端才会验证客户端证书 RequireClientCertificate = true }; } elements.Add(tcpTransportBE); CustomBinding binding = new CustomBinding(elements); // 配额配置保持不变 BindingContext context = new BindingContext(binding, new BindingParameterCollection()); XmlDictionaryReaderQuotas quotas = binaryMessageEncodingBE.GetProperty<XmlDictionaryReaderQuotas>(context); quotas.MaxArrayLength = 1048576; quotas.MaxStringContentLength = 1048576; return binding; }
2. 确认服务端的证书验证配置正确
你当前服务主机的配置是对的,不需要修改:
viewerHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom; viewerHost.Credentials.ClientCertificate.Authentication.CustomCertificateValidator = new CertValidator();
现在绑定要求客户端提供证书后,服务端就会触发这个验证逻辑,你的Validate()方法就会被调用了。
3. 客户端必须配置对应的客户端证书
注意:修改服务端绑定后,客户端必须在连接时提供有效的证书,否则会连接失败。客户端需要配置自己的证书,比如:
var client = new ViewerServiceClient(binding, endpointAddress); client.ClientCredentials.ClientCertificate.SetCertificate( StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "客户端证书的主题名");
补充说明
你之前的服务能正常运行,是因为只启用了服务端SSL加密,客户端验证服务端证书时可能绕过了自签名证书的验证(比如客户端配置了CertificateValidationMode.None),但服务端从未要求客户端提供证书,所以自定义验证器根本没机会执行。
内容的提问来源于stack exchange,提问作者Peter Dongan
相关产品推荐
相关产品推荐

