Исключение WCF - сертификат клиента не предоставлен

Исключение 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>

Ниже приводится краткое изложение выполненных мною задач, основанное на содержании многочисленных сообщений и документов.

  1. Создал самозаверяющий сертификат CA (с именем RootCATest) на сервере и поместил его в папку сертификатов доверенных корневых центров сертификации на локальном компьютере.

  2. Создал сертификат, подписанный сертификатом RootCATest (с именем TempCert) на сервере, и поместил его в папку личных сертификатов на локальном компьютере.

  3. Экспортировал сертификат TempCert и закрытый ключ.

  4. Скопировал файлы TempCert .cer и .pvk на клиентский компьютер и импортировал сертификат TempCert в папку личных сертификатов на локальном компьютере.

  5. Выполнен ICalcs.exe [путь к закрытому ключу] / grant «NT AUTHORITY \ NETWORK SERVICE»: R на сервере, используя путь к закрытому ключу для сертификата TempCert.

  6. Выполнено 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 с полномочиями

Если кто-нибудь, осведомленный о том, что здесь может происходить, сможет пролить свет на это, я буду очень признателен.


person Ol_Devel    schedule 11.01.2013    source источник


Ответы (2)


Последнее сообщение об ошибке указывает, что ваш сервер запрашивает сертификат клиента у клиента (сервер должен запросить), и клиент предоставляет сертификат, но сервер не может определить, действителен ли сертификат клиента на основе доступной информации. на серверной машине.

Поскольку вы используете самозаверяющие сертификаты (а не сертификаты, выданные ЦС), вам необходимо указать серверу, как проверять сертификаты клиентов. Вам может потребоваться установить клиентские сертификаты в хранилище сертификатов My / LocalMachine / Trusted People на сервере, чтобы проверка сертификата WCF по умолчанию могла их найти, или реализовать на сервере свой собственный валидатор клиентских сертификатов. (См. WebHttpBinding.Credentials.ClientCertificate.Authentication.CertificateValidationMode и WebHttpBinding.Credentials.ClientCertificate.Authentication.CustomCertificateValidator)

person dthorpe    schedule 06.09.2013

Я заметил, что в вашем endpoint определении вы не ссылались на behavior, который вы определили. Похоже, что вы делаете аналог вручную, используя какой-то код. Может быть проще просто подключить его в config.

Я ожидал, что ваша конечная точка будет выглядеть (больше) следующим образом:

      <endpoint address="https://10.0.0.103:8003/SBSWCFServiceHost/Operations/"
          binding="wsHttpBinding" bindingConfiguration="wsHttpEndpoint"
          contract="SBSWCFService.IOperations" name="wsHttpEndpoint"
          behaviorConfiguration="EndpointBehavior">
          <identity>
              <dns value="localhost" />
          </identity>
      </endpoint>

Это было решение, когда я получал ошибку «Сертификат клиента не предоставлен. Укажите сертификат клиента в ClientCredentials».

person tgolisch    schedule 07.10.2015