WCF 4 - TransportWithMessageCredential с использованием сертификатов X.509 для транспорта и безопасности сообщений - PullRequest
3 голосов
/ 01 октября 2011

Я пытаюсь создать службу WCF4, размещенную на IIS, которая будет использовать сертификаты X.509 для защиты сообщений и SSL с необходимой взаимной аутентификацией для безопасности транспорта (спецификация проекта требует использования WS-Security AND SSL, AFAIK только один обычно путь, но не берите в голову).

Я создал свой TestRootCA и использовал его для выдачи сертификата сервера (localhost) и сертификата клиента (TestUser).Сначала я хотел установить и проверить только безопасность транспорта, поэтому настроил IIS для использования https, настроил SSL-сертификат (сертификат localhost, который я сделал) и настроил IIS на , требующий сертификата клиента от клиентов.Затем я изменил службу web.config, создал соответствующий svcutil.conf и запустил svcutil, который успешно создал класс прокси-клиента и app.config для моего тестового приложения WinForms.Я установил сертификат при создании прокси-клиента по телефону:

var client = new ServiceClient();
client.ClientCredentials.ClientCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser, System.Security.Cryptography.X509Certificates.StoreName.My, System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectDistinguishedName, "CN=TestUser");
MessageBox.Show(client.GetData(42));

Пока все хорошо.Но когда я изменяю web.config службы для использования TrasportWithMessageCredential (вместо Transport) и указываю «Certificate» в качестве clientCredentialType для безопасности сообщений, я получаю HTTP 403 - The HTTP request was forbidden with client authentication scheme 'Anonymous', даже если я указал «Certificate».

Мой последний файл web.config выглядит следующим образом:

<system.serviceModel>
    <bindings>
        <wsHttpBinding>
            <binding name="wsHttpEndpointBinding">
                <security mode="TransportWithMessageCredential">
                    <transport clientCredentialType="Certificate"/>
                    <message clientCredentialType="Certificate"/>
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <services>
        <service behaviorConfiguration="serviceBehavior" name="Service">
            <endpoint binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding" name="wsHttpEndpoint" contract="IService" />
            <endpoint address="mex" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding" name="mexEndpoint" contract="IMetadataExchange" />
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="serviceBehavior">
                <serviceMetadata httpsGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>

и мой клиентский app.conf:

<system.serviceModel>
    <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="Certificate"/>
                    <message clientCredentialType="Certificate"/>
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <client>
        <endpoint address="https://localhost/WCFTestService/Service.svc" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpoint" contract="IService" name="wsHttpEndpoint" />
    </client>
</system.serviceModel>

Есть идеи?

РЕДАКТИРОВАТЬ:

Мне удалось заставить его работать, изменив настройки IIS SSL для сертификата клиента с требуют до accept .Кажется, что когда я внедряю защиту сообщений с использованием сертификатов по безопасности транспорта с использованием SSL, клиент использует сертификат для подписи сообщений, но не для взаимной аутентификации по SSL (он пытается войти в систему как анонимный даже если ему присвоен сертификат).

Не уверен, почему это происходит, я хотел бы получить комментарий от эксперта:).

Ответы [ 2 ]

2 голосов
/ 20 июля 2012

Как указано в вопросе, я заработал, изменив настройки IIS SSL для клиентских сертификатов с require на accept.Затем в точке входа в службу я программно проверяю сертификат удаленного пользователя (если он не нулевой и не действительный).

1 голос
/ 29 ноября 2011

Вы должны указать сертификаты, которые будут использоваться для шифрования сообщения, в разделе о поведении, поскольку они могут отличаться от тех, которые используются для установки канала https

, на сервере это будет выглядеть так:

<system.serviceModel> 
 <behaviors>     
    <serviceBehaviors>     
        <behavior name="serviceBehavior">
      <serviceCredentials>
        <serviceCertificate findValue="ServerCertificate"
                            storeLocation="CurrentUser"
                            storeName="My"
                            x509FindType="FindByIssuerName" />
        <clientCertificate>
          <certificate findValue ="ClientCertificate"
                       storeLocation="CurrentUser"
                            storeName="My"
                            x509FindType="FindByIssuerName"/>
          <authentication certificateValidationMode ="PeerTrust"/>
        </clientCertificate>
      </serviceCredentials>
            <serviceMetadata httpsGetEnabled="true" />     
            <serviceDebug includeExceptionDetailInFaults="true" />     
        </behavior>     
    </serviceBehaviors>     
</behaviors>   
</system.serviceModel> 

и сделайте то же самое на клиенте, что бы выглядело так:

<system.serviceModel>        
    <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="Certificate"/>        
                    <message clientCredentialType="Certificate"/>        
                </security>        
            </binding>        
        </wsHttpBinding>        
    </bindings>
 <behaviors>      
  <endpointBehaviors>        
    <behavior name="ClientCredentialsBehavior">
      <clientCredentials>            
        <clientCertificate x509FindType="FindBySubjectName"
                           findValue="ClientCertificate"
                           storeLocation="CurrentUser"
                           storeName="My"/>
        <serviceCertificate>
          <defaultCertificate x509FindType="FindBySubjectName"
                              findValue="ServerCertificate"
                              storeLocation="CurrentUser"
                              storeName="My"/>
        </serviceCertificate>
      </clientCredentials>
    </behavior>
  </endpointBehaviors>
</behaviors>

    <client>        
        <endpoint address="https://localhost/WCFTestService/Service.svc" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpoint" contract="IService" name="wsHttpEndpoint" behaviorConfiguration="ClientCredentialsBehavior" />        
    </client>        
</system.serviceModel>

Конечно, вы должны установить правильное расположение и имя сертификатов на сервере и клиенте.

Я надеюсь, что это все еще помогает

...