Назад | Перейти на главную страницу

Настройка IIS для запроса сертификата клиента и использования анонимной проверки подлинности

Настройка IIS для запроса сертификата клиента и использования анонимной проверки подлинности

У меня есть веб-служба WCF, которую могут использовать наши клиенты. Я хочу защитить это с помощью клиентских сертификатов. Я также буду использовать сертификат клиента для идентификации клиента.

Я заставил идентификационную часть работать, но я не могу заставить IIS требовать сертификаты клиентов.

Если я настрою IIS на прием клиентских сертификатов, связь работает, и я могу получить удостоверение клиента, используя:

ServiceSecurityContext.Current.PrimaryIdentity.Name

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

Если я настрою IIS на требование сертификата клиента, мой тестовый клиент, который должен иметь доступ, получит ошибку:

HTTP-запрос был запрещен со схемой аутентификации клиента «Анонимный».

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

Конфигурация сервера WCF:

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior name="DefaultBehavior">
        <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="true" />
        <serviceCredentials>
          <clientCertificate>
            <authentication certificateValidationMode="ChainTrust" />
          </clientCertificate>
          <serviceCertificate findValue="64343ee2c8338518e78ba698f3936dc92c90db57" x509FindType="FindByThumbprint" />
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <bindings>
    <wsHttpBinding>
      <binding name="DefaultBinding">
        <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="Certificate" />
          <message clientCredentialType="Certificate" />
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
  <services>
    <service name="WebService.Service" behaviorConfiguration="DefaultBehavior">
      <endpoint address="" binding="wsHttpBinding" bindingConfiguration="DefaultBinding" contract="WebService.IService" />
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    </service>
  </services>
</system.serviceModel>

Конфигурация клиента WCF.

<system.serviceModel>
  <behaviors>
    <endpointBehaviors>
      <behavior name="DefaultBehavior">
        <clientCredentials>
          <clientCertificate storeLocation="LocalMachine" findValue="d084c91a8f81878cd4dd991bbab348235f0fd1a3" x509FindType="FindByThumbprint" />
          <serviceCertificate>
            <authentication certificateValidationMode="ChainTrust" />
          </serviceCertificate>
        </clientCredentials>
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <bindings>
    <wsHttpBinding>
      <binding name="WSHttpBinding_IService">
        <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="Certificate" />
          <message clientCredentialType="Certificate" />
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
  <client>
    <endpoint address="https://host/WebService/Service.svc"
      behaviorConfiguration="DefaultBehavior" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService"
      contract="WebService.IService" name="WSHttpBinding_IService">
    </endpoint>
  </client>
</system.serviceModel>

Хорошо, мы сделали то же самое, что и вы. Мы работали наоборот. Сначала мы защитили IIS с помощью сертификата клиента и сервера. Мы сделали это в IIS Express (все еще в разработке, пока я публикую это). Мы разрешили в IIS express applicationhost.config для перезаписи определенных частей файла web.config. То есть: <section name="windowsAuthentication" overrideModeDefault="Allow" />

Конфигурация на стороне сервера:

<sytem.serviceModel>
<bindings>
      <wsHttpBinding>
        <binding name="ClientCert">
          <security mode="Transport">
            <transport clientCredentialType="Certificate" />
          </security>
        </binding>
      </wsHttpBinding>
</bindings>
<behaviors>
<!--We have a custom service behavior for claim based security -->
        <behavior name="wsHttpCertificateBehavior">
          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
          <serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true" />
          <serviceAuthorization serviceAuthorizationManagerType="MyNamespace.AdamAuthorizationManager, MyAssembly">
            <authorizationPolicies>
              <add policyType="MyNamespace.AdamAuthorizationPolicy, MyAssembly" />
            </authorizationPolicies>
          </serviceAuthorization>
          <serviceCredentials>
            <serviceCertificate findValue="YourServerCertificateNameWithoutCN=" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" />
            <clientCertificate>
              <authentication revocationMode="NoCheck" mapClientCertificateToWindowsAccount="true" />
            </clientCertificate>
          </serviceCredentials>
        </behavior>
</behaviors>
<services>
      <service name="MyNamespace.OrderService" behaviorConfiguration="wsHttpCertificateBehavior">
        <endpoint address="https://iisurl/OrderService.svc/ClientCert" contract="wsHttpCertificateBehavior.IOrderService" binding="wsHttpBinding" bindingConfiguration="ClientCert">
        </endpoint>
      </service>
</services>
</sytem.serviceModel>
<system.webServer>
<security>
      <authentication>
        <windowsAuthentication enabled="true" />
        <anonymousAuthentication enabled="true" />
        <iisClientCertificateMappingAuthentication defaultLogonDomain="YourDomain" enabled="true" oneToOneCertificateMappingsEnabled="true">
          <oneToOneMappings>
            <add enabled="true" certificate="Base64HashOfTheCertificate" userName="YourUserName" password="YourPassword" />
          </oneToOneMappings>
        </iisClientCertificateMappingAuthentication>
      </authentication>
      <authorization>
        <add users="*" accessType="Allow" />
      </authorization>
      <!--Require SSL *AND* require a client certificate -->
      <access sslFlags="Ssl, SslNegotiateCert, SslRequireCert" />
    </security>
</system.WebServer>

На клиенте:

<system.serviceModel>
      <wsHttpBinding>
        <binding name="ClientCertificate">
          <security mode="Transport">
            <transport clientCredentialType="Certificate"/>
          </security>
        </binding>
      </wsHttpBinding>
    <behaviors>
      <endpointBehaviors>
        <behavior name="wsHttpCertificateBehavior">
          <clientCredentials>

            <clientCertificate findValue="YourClientCertificateNameWithoutCN=" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName"/>
            <serviceCertificate>
              <authentication revocationMode="NoCheck"/>
            </serviceCertificate>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <client>

      <endpoint name="ClientCertificate" address="https://iisurl/OrderService.svc/ClientCert" contract="MyNamespace.IOrderService" binding="wsHttpBinding" bindingConfiguration="ClientCertificate" behaviorConfiguration="wsHttpCertificateBehavior">
      </endpoint>
    </client>
</system.serviceModel>

Что нам очень помогло, так это включение трассировки, ведения журнала в службе, настраиваемой политики авторизации и журналов трассировки IIS.

У нас есть iisurl сопоставлен с 127.0.0.1 в нашем файле хоста, поэтому у нас есть доверенные сертификаты. Для проверки iisClientCertificationMapping этот вне.

Не знаю, верна ли ваша настройка ssl. Для этого у нас есть сценарий PowerShell. Некоторые его части:

Создание корневого сертификата (PowerShell)

Invoke-Command -ScriptBlock{ . "C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\makecert.exe" -n "CN=YourRootCA" -r -sv YourRootCA.pvk YourRootCA.cer}


    $certFile = get-childitem $exPath | where {$_.FullName -match "GlobalVisionServicesRootCA.cer"} 
    if ($certFile -ne $NULL) { 
        echo "Discovered the YourRootCA.cer in the same folder as this script, installing it in the LocalMachine\Root certificate store.." 
        $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certFile.FullName)
        $rootStore = new-object system.security.cryptography.x509certificates.x509Store 'Root','LocalMachine'
        $rootStore.Open('ReadWrite')
        $rootStore.Add($cert) 
        $rootStore.Close() 
    }

Генерация сертификата сервера (командная строка):

makecert.exe  -sk YourDevSrvCert -iv YourRootCA.pvk -n "CN=iisurl" -ic YourRootCA.cer -sr localmachine -ss my -sky exchange -pe yourservercertificate.cer

Создание клиентского сервера (командная строка):

makecert.exe  -sk ClientDevSrvCert -iv YourRootCA.pvk -n "CN=iisurl" -ic GlobalVisionServicesRootCA.cer -sr localmachine -ss my -sky exchange -pe iisurl.cer

Привязка сертификатов к IIS (командная строка, для XP):

httpcfg.exe delete ssl -i "0.0.0.0:443"
httpcfg.exe" delete urlacl url="https://iisurl:443/"

httpcfg.exe set urlacl url="https://iisurl:443/" user=Everyone
httpcfg.exe" set ssl -i "0.0.0.0:443" -h ThumpPrint

измените ThumpPrint на ThumpPrint сертификата с именем субъекта iisurl. Я рекомендую вам полностью автоматизировать это с помощью PowerShell, у нас это есть, чтобы мы могли разрабатывать на нескольких машинах. Но я не могу пройти мимо всего этого здесь.

Я надеюсь, это поможет вам. С этой конфигурацией, если вы перейдете по https к URL-адресу iisurl / OrderService, он запросит у вас сертификат клиента. (В IE)

Вы также можете посмотреть этот журнал: C: \ WINDOWS \ system32 \ Logfiles \ HTTPERR