我有以下代码
var factory = new ChannelFactory<INewsClient>();
factory.Credentials.ClientCertificate.Certificate = GetCertificate();
factory.Endpoint.Address = new EndpointAddress("https://blabla.com/myservice/");
var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
factory.Endpoint.Binding = binding;
var channel = factory.CreateChannel();
channel.GetNews();
它适用于.NET 3.5,但不适用于.NET4.0。 Bizzare吧? 我使用的证书不在本地计算机上验证(没有链)。在3.5中,客户端证书的有效性与建立SSL无关,但在迁移到4.0时,证书在用于SSL之前已经过验证。 (我可以在CAPI2事件日志中看到错误)。导致丑陋的SecurityNegotiationException ......
堆栈追踪:
System.ServiceModel.Security.SecurityNegotiationException: Could not establish secure channel for SSL/TLS with authority 'pep.uat.dialectpayments.com'. ---> System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel. at System.Net.HttpWebRequest.GetResponse() at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout) --- End of inner exception stack trace --- Server stack trace: at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason) at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout) at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout) at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message) Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at ConsoleApplication2.Program.INewsClient.Get() at ConsoleApplication2.Program.Main(String[] args) in d:\dev\ConsoleApplication2\Program.cs:line 44
在我们的安全体系结构中,证书是根据服务器上的LDAP目录进行验证的,因此客户端无需知道完整链。
问题是,如何禁用这种新行为?
答案 0 :(得分:1)
好的,我会在这里提供自己的答案......
简而言之:似乎你不能在.NET 4 for X509上使用非持久性CSP。即您的CSP必须具有KeyContainerName才能使其正常工作。
我的GetCertificate()方法正在执行以下操作:(即非持久性)
var certificate = new X509Certificate2(@"C:\public.cer");
var rsa = RSA.Create();
rsa.FromXmlString("<RSAKeyValue>......</RSAKeyValue>");
certificate.PrivateKey = rsa;
return certificate;
将其更改为使我的示例在3.5和4.0中工作:(设置KeyContainerName将在加密文件夹中创建物理条目)
var certificate = new X509Certificate2(@"C:\public.cer");
CspParameters parameters = new CspParameters { KeyContainerName = "KeyContainer" };
var rsa = new RSACryptoServiceProvider(parameters);
rsa.FromXmlString("<RSAKeyValue>......</RSAKeyValue>");
certificate.PrivateKey = rsa;
return certificate;
为简单起见,我试图将私钥导出到.pfx文件中,但无法使用.NET 4.0中的第一种方法,但可以使用.NET 3.5。 Somwhow,私钥在.NET 4.0中无法导出。 这link帮助我解决了这个问题。
但是,很高兴知道这里3.5和4.0之间的变化。