设置 IIS 以要求客户端证书并使用匿名身份验证
我有一个 WCF Web 服务供我们的客户使用。我想使用客户端证书来保护它。我还将使用客户端证书来识别客户。
我已经使识别部分工作正常,但是无法使 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>
答案1
好的,我们做了和你一样的事情。我们反过来做。我们首先使用客户端和服务器证书保护 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 更改为主题名为 iisurl 的证书的 ThumpPrint。我建议您使用 powershell 完全自动化此操作,我们也有这个,所以我们可以在多台机器上进行开发。但我无法在这里全部完成。
希望这对您有所帮助。使用此配置,如果您通过 https 浏览 URL iisurl/OrderService,它会要求您提供客户端证书。(在 IE 中)
您还可以查看此日志:C:\WINDOWS\system32\Logfiles\HTTPERR