Исключение WCF - сертификат клиента не предоставляется. Укажите сертификат клиента в ClientCredentials.
Прочитав большую часть того, что мне удалось найти по этому поводу, и попробовав множество различных вариантов, я обнаружил, что у меня больше нет волос, чтобы тянуть за волосы, и, следовательно, этот пост.
Я хочу использовать SSL с автономной службой WCF, имеющей режим безопасности TransportWithMessageCredential с транспортом HTTP. Я использую 2 машины разработчика и тестирую по локальной сети.
Как упоминалось выше, я прочитал и внимательно следил почти за каждым примером, который демонстрирует это, но почему-то все еще имею проблемы с сертификатами.
Что касается сертификатов, то я кое-что перепробовал.
Основная идея того, что я сделал, заключалась в том, чтобы следовать тому, что дано в http://msdn.microsoft.com/en-us/library/ff647171.aspx.
Я также использовал «Как: использовать проверку подлинности сертификата и безопасность сообщений при вызове WCF из Windows Forms» в http://msdn.microsoft.com/en-us/library/ff648360.aspx в качестве основного руководства.
Сначала я протестировал службу и клиент, используя basicHttpBinding поверх Http, чтобы проверить ситуацию.
Затем я внес изменения в wsHttpBinding, SSL и сертификаты.
Когда я «добавляю ссылку на службу» на клиентском компьютере разработчика, я получаю следующее сообщение об ошибке:
- Окно с названием -
Предупреждение системы безопасности
Visual Studio обнаружила проблему с сертификатом безопасности сайта.
Выдан: RootCATest Выдан: TempCert Сертификат действителен с ---
Сертификат безопасности, выданный компанией, не находится в списке недоверенных. Это может быть надежным.
Дата сертификата безопасности действительна.
Сертификат безопасности для хоста TempCert не соответствует имени страницы, которую вы пытаетесь просмотреть.
- Вы хотите продолжить? -
Если я нажимаю «Да» для продолжения и запускаю клиентский код, возникает исключение InvalidOperationException со следующим сообщением.
«Сертификат клиента не предоставляется. Укажите сертификат клиента в ClientCredentials ».
Конфигурация сервиса выглядит следующим образом:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="CN=TempCert"
storeLocation="LocalMachine"
storeName="My" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="wsHttpEndpointBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="SBSWCFServiceHost.Operations"
behaviorConfiguration="ServiceBehavior">
<endpoint name="wsHttpEndpoint"
address=""
binding="wsHttpBinding"
bindingConfiguration="wsHttpEndpointBinding"
contract="SBSWCFServiceHost.IOperations" >
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint name="mexHttpEndpoint"
address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" >
</endpoint>
<host>
<baseAddresses>
<add baseAddress="https://10.0.0.103:8003/SBSWCFServiceHost/Operations/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
Конфигурация клиента следующая:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="EndpointBehavior">
<clientCredentials>
<clientCertificate storeLocation="LocalMachine"
storeName="My"
x509FindType="FindByThumbprint"
findValue="e4c87a961f796be6b6cab59c3760e43ffb6e941d"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="wsHttpEndpoint" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Certificate" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://10.0.0.103:8003/SBSWCFServiceHost/Operations/"
binding="wsHttpBinding" bindingConfiguration="wsHttpEndpoint"
contract="SBSWCFService.IOperations" name="wsHttpEndpoint">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
Ниже приводится краткое изложение выполненных мною задач, основанное на содержании многочисленных сообщений и документов.
Создал самозаверяющий сертификат CA (с именем RootCATest) на сервере и поместил его в папку сертификатов доверенных корневых центров сертификации на локальном компьютере.
Создал сертификат, подписанный сертификатом RootCATest (с именем TempCert) на сервере, и поместил его в папку личных сертификатов на локальном компьютере.
Экспортировал сертификат TempCert и закрытый ключ.
Скопировал файлы TempCert .cer и .pvk на клиентский компьютер и импортировал сертификат TempCert в папку личных сертификатов на локальном компьютере.
Выполнен ICalcs.exe [путь к закрытому ключу] / grant «NT AUTHORITY \ NETWORK SERVICE»: R на сервере, используя путь к закрытому ключу для сертификата TempCert.
Выполнено netsh http add sslcert ipport = o.o.o.o: 8003 certhash = [TempCert thumbprint] appid = [{application id}] на сервере
Я считаю, что близок к тому, чтобы это заработало.
Кажется довольно очевидным, что приложение недовольно сертификатом TempCert, но я не смог решить эту проблему и в значительной степени застрял.
Мы будем очень благодарны за любую помощь в отношении любых проблем в данных конфигурациях, шаги, которые я выполнил для установки правильных сертификатов, а также те, которые использовались для добавления разрешений на доступ и записи sslcert.
Большое спасибо.
После некоторых дальнейших экспериментов я заметил дополнительное поведение.
Были предприняты следующие шаги:
Я удалил сертификаты клиента и сервера и воссоздал их в соответствии с .... codeproject.com/Articles/36683/9-simple-steps-to-enable-x-509-certificates-on-wcf
Я добавил новый sslcert с помощью netsh. Затем я экспортировал клиентский сертификат с сервера и импортировал его в клиентское хранилище.
Я изменил службу app.config, добавив новую информацию о сертификатах, и запустил службу.
Я изменил клиентский app.config следующим образом:
<endpointBehaviors>
<behavior name="EndpointBehavior">
<clientCredentials>
<clientCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" findValue="WCFClient" />
<serviceCertificate>
<authentication certificateValidationMode="PeerTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
Я обновил Справочник по сервису. Процедура обновления снова выдала предупреждение системы безопасности, как и раньше.
Затем я выполнил клиент и получил эту ошибку:
«Сертификат клиента не предоставлен. Укажите сертификат клиента в ClientCredentials».
Затем я установил точку останова на «client = new WCFService.Client ();» и проверил "клиентский" экземпляр. Значение client.ClientCredentials.ClientCertificate.Certificate = null.
Затем я добавил в код после «client = new WCFService.Client ();» следующее:
X509Store store = new X509Store("My", StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection) store.Certificates;
foreach (X509Certificate2 x509 in collection)
{
if (x509.Thumbprint == "236D7D4AD95753B8F22D3781D61AACB45518E1B5")
{
client.ClientCredentials.ClientCertificate.SetCertificate(
x509.SubjectName.Name, store.Location, StoreName.My);
}
}
После выполнения этого кода client.ClientCredentials.ClientCertificate.Certificate содержал сертификат.
Затем при выполнении client.Open (); , создается исключение со следующим содержимым.
Базовое соединение было закрыто: не удалось установить доверительные отношения для безопасного канала SSL / TLS. Удаленный сертификат недействителен согласно процедуре проверки. Не удалось установить доверительные отношения для безопасного канала SSL / TLS с полномочиями
Если кто-нибудь, осведомленный о том, что здесь может происходить, сможет пролить свет на это, я буду очень признателен.