WCF 证书身份验证不起作用

WCF Certificate Authentication not working

我构建了一个 WCF helloworld 客户端和服务器。我想在它们之间使用证书认证。

我得到的错误是"The caller was not authenticated by the service."

我使用 makecert.exe 创建了两个证书。客户端上的证书安装在'Personal'和'Trusted People'和'Third-Party Root Certification Authorities'下。我复制了证书,因为我不知道它是否应该只在一个标题下

我的服务器 webconfig 如下

            <?xml version="1.0"?>
            <configuration>
              <appSettings>
                <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
              </appSettings>
              <system.web>
                <compilation debug="false" targetFramework="4.5.1"/>
                <httpRuntime targetFramework="4.5.1"/>
              </system.web>
              <system.serviceModel>
                <services>
                  <service behaviorConfiguration="BusinessToBusiness" name="TestHelloWork.Service1">

                    <endpoint address="" binding="wsHttpBinding"  bindingConfiguration="BindingConfig" contract="TestHelloWork.IService1" /> 
                            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
                    <host>
                      <baseAddresses>
                        <add baseAddress="http://win-gat-web01:7777/Service1"/>
                      </baseAddresses>
                    </host>
                  </service>
                </services>
                <bindings>  
                  <wsHttpBinding>  
                    <binding name="BindingConfig">
                     <security>
                        <message clientCredentialType = "Certificate"/>
                     </security>
                    </binding>  
                  </wsHttpBinding>  
               </bindings>  
                <behaviors>
                  <endpointBehaviors>
                    <behavior name="webBehavior">
                      <webHttp/>
                    </behavior>
                  </endpointBehaviors>
                  <serviceBehaviors>
                    <behavior>
                      <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
                      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
                      <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
                      <serviceDebug includeExceptionDetailInFaults="true"/>
                    </behavior>
                    <behavior name="BusinessToBusiness">
                     <serviceCredentials>
                        <clientCertificate>
                           <authentication certificateValidationMode = "PeerTrust"/>
                        </clientCertificate>
                        <serviceCertificate findValue="WCfServer"
                storeLocation="LocalMachine"
                storeName="My"
                x509FindType="FindBySubjectName" />         
                     </serviceCredentials>
                     <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
                    </behavior>     
                  </serviceBehaviors>
                </behaviors>
                <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
              </system.serviceModel>
            </configuration>

客户端web.config如下

            <?xml version="1.0"?>

            <!--
              For more information on how to configure your ASP.NET application, please visit
              http://go.microsoft.com/fwlink/?LinkId=169433
              -->

            <configuration>

                <system.web>
                  <compilation debug="true" targetFramework="4.5.1" />
                  <httpRuntime targetFramework="4.5.1" />
                </system.web>
              <system.serviceModel>
            <bindings>
              <wsHttpBinding>
                <binding name="WSHttpBinding_IService1">
                  <security>
                    <message clientCredentialType="Certificate" />

                  </security>
                </binding>
              </wsHttpBinding>
            </bindings>
            <client>
              <endpoint address="http://myserver:7777/Service.svc" binding="wsHttpBinding"
                bindingConfiguration="WSHttpBinding_IService1" contract="ServiceReference1.IService1"
                name="WSHttpBinding_IService1" behaviorConfiguration="CustomBehavior">
                <identity>
                  <dns value="WCfServer" />
                </identity>
              </endpoint>
            </client>
            <behaviors>
              <endpointBehaviors>
                <behavior name="CustomBehavior">
                  <clientCredentials>
                    <clientCertificate findValue="WcfClient" x509FindType="FindBySubjectName"

                      storeLocation="CurrentUser" storeName="My" />
                    <serviceCertificate>
                      <authentication certificateValidationMode="PeerTrust"/>
                    </serviceCertificate>
                  </clientCredentials>
                </behavior>
              </endpointBehaviors>
            </behaviors>
            </system.serviceModel>
            </configuration>

客户端证书安装在'Personal'

知道哪里出了问题吗?我已经用谷歌搜索并意识到它们应该在同一个域中?但他们是。另外,当我的服务是外部服务时,域将如何工作?

尝试启用 CAPI2 日志。它是包含证书验证信息的特殊日志(默认情况下未启用)。如果您的问题在于证书验证程序失败,您会在那里找到有用的信息。查找错误。就我而言,它类似于

  • 已处理证书链,但终止于不受信任提供者信任的根证书。
  • 无法为受信任的根颁发机构构建证书链。
  • 吊销功能无法检查吊销...

就我而言,我有

  • Client.pfx 导入到客户端上的 CurrentUser\My(个人)商店。
  • 颁发 ​​client.pfx 的 CA 证书 (ClientCA) 已导入到客户端 LocalMachine 存储区和服务器上 LocalMachine 存储区的受信任的根授权中心。
  • server.pfx 导入到 LocalMachine\My 服务器上的(个人)商店
  • 颁发 ​​server.pfx 的 CA 证书 (ServerCA) 在客户端的 LocalMachine 存储和服务器的 LocalMachine 存储中导入到受信任的根授权机构。
  • 客户端和服务器都可用的客户端 CA 的 CRL
  • 服务器 CA 的 CRL 可从客户端和服务器获得

但是您正在使用 PeerTrust 证书验证模式,因此根据 WCF 演示中的评论,我有

Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate is in the user's Trusted People store, then it will be trusted without performing a validation of the certificate's issuer chain. This setting is used here for convenience so that the sample can be run without having to have certificates issued by a certificate authority (CA).

我假设证书应该这样放置:

  • client.cer(仅来自 client.pfx 的证书)导入到服务器
  • 上 LocalMachine 存储中的可信人员存储
  • server.cer(仅来自 client.pfx 的证书)导入到客户端
  • 上 CurrentUser 存储中的受信任人员存储

确认您已将服务器私钥的权限授予运行 IIS WCF 服务的 AppPool(默认池为 IIS APPPOOL\DefaultAppPool) 可以使用 mmccertlm.msc 通过右键单击服务器证书然后 All Tasks -> Manage Private Keys ... 来完成。确认您没有 选择 AD,因为 IIS APPPOOL 是一个本地组。添加帐户 IIS APPPOOL\your_pool_name 并点击确定。

如果您的 AppPool 中有默认设置,如 Identity 设置为 AplicationPoolIdentity 而不是自定义帐户(通常使用来自 AD 的托管服务帐户)和 Load User Profile 设置为 true.

您遇到的 WCF 证书身份验证问题很可能与使用 MakeCert 生成自签名证书时使用的选项有关。

尤其要确保您的证书支持必要的 options/purposes。 (例如,证书的预期用途字段应包含适当的值,例如 "Server Authentication" 或 "Client Authentication"。)

来自 Microsoft 的以下 link 详细介绍了该过程。
https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-create-temporary-certificates-for-use-during-development

注意:我们的团队在使用 SelfCert 工具快速生成开发自签名证书时运气不错。