Настройка 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