Сертификат SSL для аутентификации WCF - PullRequest
1 голос
/ 12 августа 2011

Я разработал приложение, которое запускает несколько служб 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();

Обратите внимание, что я удалил часть, касающуюся моей пользовательской аутентификации, чтобы иметь более чистый код

1 Ответ

4 голосов
/ 12 августа 2011

Ваш клиент хочет безопасности за пределами домена Windows = ваш клиент хочет сертификат. Нет сертификата = нет безопасности. Это то, что вы должны объяснить своему клиенту.

Вам просто нужно иметь сертификат с закрытым ключом на сервере, и клиент должен доверять этому сертификату (ему не нужно устанавливать его, если он доверяет издателю). Что это значит? У вас есть три варианта:

  • Ваш клиент должен купить сертификат у надежного издателя, и ваши клиенты будут просто работать
  • У вашего клиента должен быть установлен собственный центр сертификации, который будет генерировать сертификат, а клиенты должны иметь сертификат центра в своем хранилище доверенных корневых органов (каждая более крупная компания имеет свой собственный центр сертификации).
  • Вы будете использовать самозаверяющий сертификат в производстве. Это "менее безопасно" и не рекомендуется. Менее безопасный означает, что ваш клиент должен доверять самозаверяющему сертификату, и он не может проверить цепочку сертификатов = он не может проверить, что сертификат был выдан доверенным органом, и он не может проверить, что центр сертификации отозвал скомпрометированный сертификат. В этом случае вы должны установить сервисный сертификат на каждом клиенте - это единственный способ доверять самоподписанному сертификату (сама установка - это доверие).

Так работает система безопасности. Вы можете создать свой собственный - вы приложите к этому большие усилия, но в конце вам все еще понадобится PKI (инфраструктура закрытого ключа) с асимметричным шифрованием, чтобы сделать его действительно безопасным. Сертификаты в основном касаются упаковки, хранения и передачи открытых и закрытых ключей.

...