我正在为使用 SSL 和证书进行相互身份验证的 WCF Web 服务开发概念证明。
因此,我有 2 个证书均由有效的证书颁发机构提供(这些是生产证书,而不是开发证书)。以下是证书的链和存储位置:
服务器证书链
- 颁发者根 CA
- 中级 1 CA
- 服务器认证证书
我不知道这个细节是否重要:服务器证书是域的通配符证书(* .mydomain.com)
客户端证书链
- 颁发者根 CA
- 中级 2 CA
- 客户端认证证书
颁发者根 CA 是两个证书的通用根 CA。
中间证书是不同的。
店面位置
颁发者根 CA 已导入服务器和客户端计算机上的受信任根 CA中间 CA 1 和 2 已导入服务器和客户端的中间 CA颁发者和中间证书仅具有两个公钥。
服务器证书已导入服务器机器上的个人。该证书有一个私钥。服务器证书已导入客户端计算机上的个人。该证书只有一个公钥。客户端身份验证证书已在服务器和客户端计算机上导入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:无法为具有权限“myservice.mydomain.com”的 SSL/TLS 建立安全通道。---> System.Net.WebException:请求被中止:无法创建 SSL/TLS 安全通道。在 System.Net.HttpWebRequest.GetResponse() 在 System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout) --- 内部异常堆栈跟踪结束 ---
经过调查,我在服务器的事件查看器中发现了一个条目:
处理异常。异常详细信息:System.IdentityModel.Tokens.SecurityTokenValidationException: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 token) 在 System.IdentityModel.Selectors .SecurityTokenAuthenticator.ValidateToken(SecurityToken token) 在 System.ServiceModel.Channels.HttpsChannelListener
1.CreateSecurityProperty(X509Certificate2 certificate, WindowsIdentity identity, String authType) at System.ServiceModel.Channels.HttpsChannelListener
1.ProcessAuthentication(IHttpAuthenticationContext authenticationContext) 在 System.ServiceModel.Activation.HostedHttpContext.OnProcessAuthentication() 在 System.ServiceModel.Channels.HttpRequestContext.ProcessAuthentication() 在 System. ServiceModel.Channels.HttpChannelListener1.HttpContextReceivedAsyncResult
1.Authenticate() 在 System.ServiceModel.Channels.HttpChannelListener 1.ProcessHttpContextAsync(1.HttpContextReceivedAsyncResult
)
关于这个异常,我发现问题出在客户端认证证书的链验证上,但不知道为什么。在这一点上,我被卡住了!我不知道我的证书有什么问题,也不知道如何找到解决方案。
我真的希望有人可以帮助我解决这个问题。
编辑: 我们已经用另一个客户端证书测试了证书链在服务器和客户端证书上是相同的,它不会改变任何东西。