设置 IIS 以要求客户端证书并使用匿名身份验证

Pal*_*pie 5 ssl certificate wcf iis-7.5 ssl-certificate

设置 IIS 以要求客户端证书并使用匿名身份验证

我有一个 WCF Web 服务供我们的客户使用。我想使用客户端证书来保护它。我还将使用客户端证书来识别客户。

我已经使标识部分工作,但我不能使 IIS 需要客户端证书。

如果我将 IIS 设置为接受客户端证书,则通信正常,我可以使用以下方法获取客户端身份:

ServiceSecurityContext.Current.PrimaryIdentity.Name
Run Code Online (Sandbox Code Playgroud)

但是我也可以在没有客户端证书的情况下访问该站点。我不确定那些没有阅读 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>
Run Code Online (Sandbox Code Playgroud)

客户端 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>
Run Code Online (Sandbox Code Playgroud)

Pre*_*hts 1

好吧,我们已经做了和你一样的事情。我们却以相反的方式工作。我们首先使用客户端和服务器证书保护 IIS。我们在 IIS Express 上做到了这一点(在我发布此内容时仍在开发中)。我们允许 IIS Expressapplicationhost.config覆盖 web.config 的特定部分。IE:<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>
Run Code Online (Sandbox Code Playgroud)

在客户端:

<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>
Run Code Online (Sandbox Code Playgroud)

对我们帮助很大的是在服务中启用跟踪、日志记录以及自定义授权策略和 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() 
    }
Run Code Online (Sandbox Code Playgroud)

生成服务器证书(命令行):

makecert.exe  -sk YourDevSrvCert -iv YourRootCA.pvk -n "CN=iisurl" -ic YourRootCA.cer -sr localmachine -ss my -sky exchange -pe yourservercertificate.cer
Run Code Online (Sandbox Code Playgroud)

生成服务器客户端(命令行):

makecert.exe  -sk ClientDevSrvCert -iv YourRootCA.pvk -n "CN=iisurl" -ic GlobalVisionServicesRootCA.cer -sr localmachine -ss my -sky exchange -pe iisurl.cer
Run Code Online (Sandbox Code Playgroud)

将证书绑定到 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
Run Code Online (Sandbox Code Playgroud)

将 ThumpPrint 更改为主题名为 iisurl 的证书的 ThumpPrint。我建议您使用 powershell 完全自动化,我们有这个,这样我们就可以在多台机器上进行开发。但我不能把这一切都抛在这儿。

我希望这可以帮助你。使用此配置,如果您通过 https 浏览到 url iisurl/OrderService,它会要求您提供客户端证书。(在 IE 中)

您还可以查看此日志:C:\WINDOWS\system32\Logfiles\HTTPERR