セットアップIISクライアント証明書を要求し、匿名認証を使用するには
お客様が使用できるWCF Webサービスがあります。クライアント証明書を使用してこれを保護したい。また、クライアント証明書を使用して顧客を識別します。
識別部分を機能させましたが、IISクライアント証明書を要求するようにすることはできません。
クライアント証明書を受け入れるようにIISを設定した場合、通信は機能し、次を使用してクライアントIDを取得できます。
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>
OK、私たちはあなたと同じことをしました。私たちは逆に働きました。最初にIISをクライアントとサーバーの証明書で保護しました。これはIIS Express(これを投稿している間、まだ開発中です)で行いました。 IISエクスプレス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トレースログの有効化です。
Hostファイルではiisurl
が127.0.0.1にマッピングされているため、信頼できる証明書を持っています。 iisClientCertificationMappingチェックの場合 this outです。
あなたの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をサブジェクト名iisurlの証明書のThumpPrintに変更します。私はこれをpowershellで完全に自動化することをお勧めします。これにより、複数のマシンで開発できるようになります。しかし、ここではすべてを過ぎることはできません。
これがお役に立てば幸いです。この構成で、httpsを参照してURL iisurl/OrderServiceにアクセスすると、クライアント証明書を要求されます。 (IEの場合)
次のログも確認できます:C:\ WINDOWS\system32\Logfiles\HTTPERR