Я разработал приложение, которое запускает несколько служб WCF, которые используют SecurityMode.Message для шифрования связи.
Это работает, но очень сложно, потому что мы должны сгенерировать 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();
Обратите внимание, что я удалил часть, касающуюся моей пользовательской аутентификации, чтобы иметь более чистый код