如何强制WCF客户端发送客户端证书?

时间:2010-11-03 19:41:48

标签: wcf https certificate ssl

我正在尝试通过https访问公开托管的SOAP Web服务(而不是WCF),我收到的错误是我以前从未见过的。首先,这是事实:

  • 此服务需要客户端证书。我有一个证书,该证书由与服务器证书相同的CA签名。
  • 我知道网址可用,因为我可以在Internet Explorer中点击它。 IE显示“选择证书”窗口,如果我选择它(并忽略server-host-name-does-not-match-certificate错误),它会继续并给我一个HTTP 500错误。
  • 如果我在Chrome中打开网站,在选择证书并忽略错误后,我会收到有关WSA Action = null的正常错误消息。
  • 如果我在FireFox中打开网站,在忽略错误后,我会得到一个页面,说明服务器无法验证我的证书。它从未要求我选择一个,所以这是完全合理的。

现在,例外:

Error occurred while executing test 12302: System.ServiceModel.Security.SecurityNegotiationException: Could not establish secure channel for SSL/TLS with authority 'ihexds.nist.gov:9085'. ---> System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

我已经跟踪了与WireShark的交互,但由于我不是TLS协议的专家,我可能会错过有关正在发生的事情的线索。然而,这就是我所看到的:

  1. C - > S客户你好
    • 包含随机数,日期/时间,支持的密码套件等内容
  2. S - > C服务器Hello,证书,证书请求,服务器Hello完成
    • 包含服务器的证书和客户端证书的请求
  3. C - > S证书,客户密钥交换,更改密码规范,加密握手消息
    • 这里是有趣的部分 - 此数据包的第一部分是证书握手,我假设客户端证书是,但没有证书(证书长度:0)。
  4. S - > C警报(级别:致命,描述:错误证书)
    • 嗯,是的,没有发送证书。
  5. 我的绑定设置如下:

    <binding name="https_binding">
        <textMessageEncoding />
        <httpsTransport useDefaultWebProxy="false" />
    </binding>
    

    我的行为设置如下:

    <behavior name="clientcred">
        <clientCredentials>
            <clientCertificate findValue="69b6fbbc615a20dc272a79caa201fe3f505664c3" storeLocation="CurrentUser" storeName="My" x509FindType="FindByThumbprint" />
            <serviceCertificate>
                <authentication certificateValidationMode="None" revocationMode="NoCheck" />
            </serviceCertificate>
        </clientCredentials>
        <messageInspector />
    </behavior>
    

    我的端点设置为同时使用绑定和行为。为什么WCF在创建https连接时拒绝发送证书?

3 个答案:

答案 0 :(得分:9)

我解决了这个问题,但我不明白为什么这个配置改变了它。我更改了这一行:

<httpsTransport useDefaultWebProxy="false" />

到此:

<httpsTransport useDefaultWebProxy="false" requireClientCertificate="true" />

神奇地开始工作了。我已经明白requireClientCertificate“旋钮”是服务器端的,所以我在争吵时没有尝试过。显然我错了。

答案 1 :(得分:2)

应该有来自服务器的CertificateRequest,命名可接受的证书类型和CA.如果您的证书与那些证书不符,则不会发送。

答案 2 :(得分:0)

协商使用哪种安全协议可能是一个问题。特别是我认为服务器可能不喜欢WCF尝试使用TLS 1.0。

要查看是否是这种情况,请尝试在调用服务之前添加以下内容

System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Ssl3

可以在客户端代码中添加,也可以将其放在IEndpointBehavior