WCF身份验证的SSL证书

时间:2011-08-12 09:04:09

标签: c# wcf ssl ssl-certificate wcf-security

我开发了一个应用程序,它启动了几个使用SecurityMode.Message加密通信的WCF服务。

它正在运行,但是,它非常复杂,因为我们必须生成SSL证书并将其放在特定的商店,服务器和客户端上。

问题是将使用该程序的客户:

  • 不在域中(事实上,服务器肯定会在域中,而不是在客户端
  • 不想购买证书

那么我最好的投篮是什么?我只需要加密数据,我不需要确保我连接到正确的主机。

我知道我不是最好的情况,但某些特定用户会使用该应用程序。

这是我的代码的一部分,它建立了连接:

服务器端:

ServiceHost host = new ServiceHost(typeof(MyServiceType))
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;
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
host.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, ConfigurationManager.AppSettings["Hostname"]);
host.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
host
.AddServiceEndpoint(services[port], binding, String.Format("http://localhost:{0}", port));

客户端:

string remoteAddress = String.Format("{0}://{1}:{2}", Tools.GetDescription(accessInfo.ServiceHost.Protocol), accessInfo.ServiceHost.HostName, accessInfo.PortNumber);


// 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<TService> channelFactory = new ChannelFactory<TService>(binding, remoteAddress);

_service = channelFactory.CreateChannel();

请注意,我删除了有关我的自定义身份验证的部分以获得更干净的代码

1 个答案:

答案 0 :(得分:4)

您的客户希望Windows域外的安全性=您的客户需要证书。没有证书=没有安全性。这是您必须向您的客户解释的内容。

您只需要在服务器上拥有带私钥的证书,并且客户端必须信任该证书(如果它信任发布者,则不必安装它)。这是什么意思?您有三种选择:

  • 您的客户必须从受信任的发布商处购买证书,您的客户才能使用
  • 您的客户必须安装自己的证书颁发机构才能生成证书,客户必须在其受信任的根管理机构商店中拥有该机构的证书(每个大型公司都有自己的证书颁发机构)。
  • 您将在制作中使用自签名证书。这是“不太安全”,不推荐。安全性较低意味着客户端必须信任自签名证书,并且无法验证证书链=它无法验证证书是否由受信任的颁发机构颁发,并且无法验证证书颁发机构是否已撤销受损证书。在这种情况下,您必须在每个客户端上安装服务证书 - 这是信任自签名证书的唯一方法(安装本身实际上是信任)。

这就是安全工作的方式。您可以自己构建 - 您将付出巨大努力,但最终您仍需要使用非对称加密的PKI(私钥基础结构)来确保其安全。证书主要是关于包装,存储和传输公钥和私钥。