使用企业CA的WCF SSL证书

对于应用程序,我需要为WCF服务提供SSL证书,

所以我们安装了它。 如果我使用带有网络浏览器的互联网浏览器通过https,我没有问题,没有警告,没有,所以我认为这个证书被认为对Windows有效。

问题是,当我尝试连接到我的WCF服务器时,我收到此错误:

The X.509 certificate CN=myHostName, OU=tom, O=myDomainName, 

L = MyLocation,S = SO,C = CH链构建失败。 使用的证书具有无法validation的信任链。 替换证书或更改certificateValidationMode。 撤销function无法检查吊销,因为吊销服务器处于脱机状态。

有什么不对? 我怎么知道链的哪个部分无效? 有没有办法知道缺少的部分是什么?

这是我的代码服务器:

 ServiceHost myHost = new ServiceHost(typeof(MyService)); WSHttpBinding binding = new WSHttpBinding { ReaderQuotas = { MaxStringContentLength = int.MaxValue, MaxArrayLength = int.MaxValue, MaxDepth = int.MaxValue, MaxBytesPerRead = int.MaxValue, MaxNameTableCharCount = int.MaxValue }, MaxReceivedMessageSize = int.MaxValue }; TimeSpan timeoutSpan = TimeSpan.FromMilliseconds(timeout); binding.CloseTimeout = timeoutSpan; binding.OpenTimeout = timeoutSpan; binding.ReceiveTimeout = timeoutSpan; binding.SendTimeout = timeoutSpan; binding.ReliableSession.InactivityTimeout = timeoutSpan; binding.MaxBufferPoolSize = int.MaxValue; //we set the security type binding.Security.Mode = SecurityMode.Message; binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName; binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None; //we set the server's certificate myHost.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, ConfigurationManager.AppSettings["Hostname"]); myHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None; //we add the endPoint(and we indicate which methods are exposed through the interface myHost.AddServiceEndpoint(services[port], binding, String.Format("http://localhost:{0}", port)); //Some services doesn't need an authentication if (!servicesWithoutAuth.Contains(services[port])) { //We set the authentifier: myHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom; myHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNameValidator(); myHost.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.Custom; //we set the AuthorizationPolicy List policies = new List { new CustomAuthorizationPolicy() }; myHost.Authorization.ExternalAuthorizationPolicies = policies.AsReadOnly(); } else { //We set the authentifier: myHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom; myHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new NoUserNamePasswordValidator(); } //We bypass the certificate verification(our certificate is only self signed) //HACK Only to desactivate the SSL check: ServicePointManager.ServerCertificateValidationCallback += ValidateCertificate; //HACK: Remove when debug finished private static bool ValidateCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors) { return true; } 

我的客户方:

 // the remote adress is of the form "net.tcp://localhost:8000" string remoteAddress = String.Format("{0}://{1}:{2}", Tools.GetDescription(accessInfo.ServiceHost.Protocol), accessInfo.ServiceHost.HostName, accessInfo.PortNumber); // HACK: binding depends on protocol -> switch over accessInfo.ServiceHost.Protocol // avoid seralization/deserialization problems with large XML's WSHttpBinding binding = new WSHttpBinding(); binding.ReaderQuotas.MaxStringContentLength = int.MaxValue; binding.ReaderQuotas.MaxArrayLength = int.MaxValue; binding.MaxReceivedMessageSize = int.MaxValue; binding.ReaderQuotas.MaxStringContentLength = int.MaxValue; binding.ReaderQuotas.MaxArrayLength = int.MaxValue; binding.ReaderQuotas.MaxDepth = int.MaxValue; binding.ReaderQuotas.MaxBytesPerRead = int.MaxValue; binding.ReaderQuotas.MaxNameTableCharCount = int.MaxValue; TimeSpan timeoutSpan = DateTime.Now.AddMinutes(30) - DateTime.Now; binding.CloseTimeout = timeoutSpan; binding.OpenTimeout = timeoutSpan; binding.ReceiveTimeout = timeoutSpan; binding.SendTimeout = timeoutSpan; binding.ReliableSession.InactivityTimeout = timeoutSpan; //++ binding.MaxBufferPoolSize = int.MaxValue; //we set the security type binding.Security.Mode = SecurityMode.Message; binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName; binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None; ChannelFactory channelFactory = new ChannelFactory(binding, remoteAddress); channelFactory.Credentials.UserName.UserName = ((UsernamePasswordAuthentication)authInfos).Username; channelFactory.Credentials.UserName.Password = ((UsernamePasswordAuthentication)authInfos).Password; //We set the maxItemsInObjectGraph foreach (OperationDescription op in channelFactory.Endpoint.Contract.Operations) { DataContractSerializerOperationBehavior dataContractBehavior = op.Behaviors.Find(); if (dataContractBehavior != null) { dataContractBehavior.MaxItemsInObjectGraph = int.MaxValue; } } SamlSecurityTokenAuthenticator authenticator = new SamlSecurityTokenAuthenticator(new List(new SecurityTokenAuthenticator[] { new RsaSecurityTokenAuthenticator(), new X509SecurityTokenAuthenticator(X509CertificateValidator.None) }), TimeSpan.FromDays(5)); _service = channelFactory.CreateChannel(); 

我怎么知道链的哪个部分无效? 有没有办法知道缺少的部分是什么?

嗯,根据我的经验,如果您打开密钥库并查看它,您应该看到您的证书明确形成一个链。 我不知道您使用什么工具来查看您的密钥库(或者如果您使用的是Windows密钥库),但是当您查看密钥时,您应该看到某种链。 如果链条形成正确,它将正确显示,并且没有任何缺失部件。

我的猜测是,当您导入证书回复时,由于某种原因它不会形成链。 换句话说,您的证书作为“未链接”的公钥存在于您的密钥库中。