具有相互身份验证证书的WCF Web服务在客户端链信任验证上失败

时间:2014-03-05 06:49:58

标签: wcf ssl-certificate wcf-security mutual-authentication

我正在使用SSL和证书进行相互身份验证的WCF Web服务的概念验证。

因此,我有2个证书都由有效的证书颁发机构提供(这些是生产证书,而不是开发证书)。以下是证书的链和商店位置:

  

服务器证书链

     
      
  • 颁发者根CA.   
        
    • 中级1 CA.   
          
      • 服务器身份验证证书
      •   
    •   
  •   
     

我不知道这个细节是否重要:服务器证书是域的通配符证书(* .mydomain.com

     

客户证书链

     
      
  • 颁发者根CA.   
        
    • 中级2 CA.   
          
      • 客户端身份验证证书
      •   
    •   
  •   
     

颁发者根CA是两个证书的通用根CA.

     

中间体证书是不同的。

     

商店位置

     

颁发者根CA已导入服务器和客户端计算机上的受信任的根CA   中间CA 1&已在服务器和客户端上将2导入到 Intermediate CA 中   发行人和中间人证书只有公钥。

     

服务器证书已导入服务器计算机上的 Personal 。此证书具有私钥。   服务器证书已导入客户端计算机上的 Personal 。此证书仅具有公钥。   客户端身份验证证书已导入服务器和客户端计算机上的 Personal 。这些证书都有私钥。

我使用框架C#4.0在IIS 8.5中创建了一个简单的WCF应用程序项目。 我在项目创建时使用默认提供的示例类,我刚将其重命名为 DemoService.svc 。 然后,我创建了客户端(我使用winform应用程序为目标用户提供了一个图形界面来查看结果)并添加了Web服务引用。

然后,我修改了服务配置以设置相互身份验证。全部通过web.config完成:

  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="demoServiceBehavior">
          <serviceAuthorization principalPermissionMode="UseWindowsGroups"></serviceAuthorization>
          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" />
          <serviceDebug includeExceptionDetailInFaults="false" />
          <serviceCredentials>
            <serviceCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" findValue="*.mydomain.com"/>
            <clientCertificate>
              <authentication certificateValidationMode="ChainTrust" revocationMode="NoCheck" mapClientCertificateToWindowsAccount="true"
                trustedStoreLocation="LocalMachine"/>
              <certificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"
                findValue="myservice.mydomain.com"/>
            </clientCertificate>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>
        <binding name="demoServiceBinding">
          <security mode="Transport">
            <transport clientCredentialType="Certificate"></transport>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true">
      <serviceActivations>
        <add service="WcfMutualAuthenticationServiceDemo.DemoService" relativeAddress="DemoService.svc" />
      </serviceActivations>
    </serviceHostingEnvironment>
    <services>
      <service name="WcfMutualAuthenticationServiceDemo.DemoService" behaviorConfiguration="demoServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="https://myservice.mydomain.com/"/>
          </baseAddresses>
        </host>
        <endpoint name="demoServiceEndpoint"
                  address=""
                  binding="basicHttpBinding"
                  bindingConfiguration="demoServiceBinding"
                  contract="WcfMutualAuthenticationServiceDemo.IDemoService"></endpoint>
      </service>
    </services>
  </system.serviceModel>

我修改了客户端配置以设置相互身份验证:

<system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="demoClientBehavior">
          <clientCredentials>
            <clientCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"
              findValue="myservice.dekra-automotivesolutions.com"/>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>
        <binding name="demoClientBinding">
          <security mode="Transport">
            <transport clientCredentialType="Certificate"></transport>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="https://myservice.mydomain.com/DemoService.svc"
                behaviorConfiguration="demoClientBehavior"
                binding="basicHttpBinding"
                bindingConfiguration="demoClientBinding"
                contract="DemoServiceValidReference.IDemoService"
                name="demoServiceEndpoint" />
    </client>
</system.serviceModel>

当我通过客户端调用Web服务时,它会返回一个异常:

  

System.ServiceModel.Security.SecurityNegotiationException:无法   为权威人士建立SSL / TLS安全通道   'myservice.mydomain.com'。 ---&GT;   System.Net.WebException:请求已中止:无法创建   SSL / TLS安全通道。在System.Net.HttpWebRequest.GetResponse()   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan)   超时)---内部异常堆栈跟踪结束---

经过调查,我在服务器的事件查看器中找到了一个条目:

  

处理异常。例外细节:   System.IdentityModel.Tokens.SecurityTokenValidationException:The   X.509证书CN = myservice.mydomain链构建失败。该   使用的证书具有无法验证的信任链。   替换证书或更改certificateValidationMode。一个   认证链处理正确,但CA之一   策略提供者不信任证书。

     

在   System.IdentityModel.Selectors.X509CertificateChain.Build(X509Certificate2   证书)   System.IdentityModel.Selectors.X509CertificateValidator.ChainTrustValidator.Validate(X509Certificate2   证书)   System.IdentityModel.Selectors.X509SecurityTokenAuthenticator.ValidateTokenCore(SecurityToken   令牌)   System.IdentityModel.Selectors.SecurityTokenAuthenticator.ValidateToken(SecurityToken   令牌)   System.ServiceModel.Channels.HttpsChannelListener 1.CreateSecurityProperty(X509Certificate2 certificate, WindowsIdentity identity, String authType) at System.ServiceModel.Channels.HttpsChannelListener 1.ProcessAuthentication(IHttpAuthenticationContext   authenticationContext)at   System.ServiceModel.Activation.HostedHttpContext.OnProcessAuthentication()   在   System.ServiceModel.Channels.HttpRequestContext.ProcessAuthentication()   在   System.ServiceModel.Channels.HttpChannelListener 1.HttpContextReceivedAsyncResult 1.Authenticate()   在   System.ServiceModel.Channels.HttpChannelListener 1.HttpContextReceivedAsyncResult 1.ProcessHttpContextAsync()

关于这个例外,我发现问题出在客户端身份验证证书的链验证上,但我不知道为什么。 此时,我被困住了! 我不知道我的证书有什么问题,我不知道如何找到解决方案。

我真的希望有人可以帮我解决这个问题。

修改: 我们已经使用另一个客户端证书进行测试,认证链在服务器和客户端证书上是相同的,它不会改变任何内容。

1 个答案:

答案 0 :(得分:1)

今天发现了解决方案:客户端和服务器上的配置正常。 这是对IIS服务器证书映射的错误配置,未配置但未启用功能。