简体   繁体   English

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

[英]How to force WCF client to send client certificate?

I'm trying to access a publicly-hosted SOAP web service (not WCF) over https, and I'm getting an error that I've never seen before. 我试图通过https访问公开托管的SOAP Web服务(而不是WCF),我收到的错误是我以前从未见过的。 First, here are the facts: 首先,这是事实:

  • This service requires client certificates. 此服务需要客户端证书。 I have a certificate that is signed by the same CA as the server's certificate. 我有一个证书,该证书由与服务器证书相同的CA签名。
  • I know that the URL is available, as I can hit it in Internet Explorer. 我知道URL可用,因为我可以在Internet Explorer中找到它。 IE brings up the "choose certificate" window, and if I pick it (and ignore the server-host-name-does-not-match-certificate error), it goes on and gives me an HTTP 500 error. IE打开“选择证书”窗口,如果我选择它(并忽略server-host-name-does-not-match-certificate错误),它会继续并给我一个HTTP 500错误。
  • If I open the site in Chrome, after picking the cert and ignoring the error, I get a normal error message about WSA Action = null. 如果我在Chrome中打开网站,在选择证书并忽略错误后,我会收到有关WSA Action = null的正常错误消息。
  • If I open the site in FireFox, after ignoring the error, I get a page about how the server couldn't validate my certificate. 如果我在FireFox中打开网站,忽略错误后,我会得到一个页面,说明服务器无法验证我的证书。 It never asked me to pick one, so that makes perfect sense. 它从未要求我选择一个,所以这是完全合理的。

Now, the exception: 现在,例外:

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)

I've traced the interaction with WireShark, but because I'm not an expert in the TLS protocol, I could be missing clues as to what's going on. 我跟踪了与WireShark的交互,但由于我不是TLS协议的专家,我可能会错过关于发生了什么的线索。 Here, however, is what I do see: 然而,在这里,我看到的是:

  1. C -> S Client Hello C - > S客户端你好
    • Contains things like a random number, date/time, cypher suites supported, etc 包含随机数,日期/时间,支持的密码套件等内容
  2. S -> C Server Hello, Certificate, Certificate Request, Server Hello Done S - > C服务器Hello,证书,证书请求,服务器Hello完成
    • Contains the server's certificate, and a request for a client certificate 包含服务器的证书和客户端证书的请求
  3. C -> S Certificate, Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message C - > S证书,客户密钥交换,更改密码规范,加密握手消息
    • HERE IS THE INTERESTING PART -- The first part of this packet is the Certificate handshake, where I assume the client certificate would be, but there are no certificates present (Certificates Length: 0). 这是有趣的部分 - 这个数据包的第一部分是证书握手,我假设客户端证书是,但没有证书(证书长度:0)。
  4. S -> C Alert (Level: Fatal, Description: Bad Certificate) S - > C警报(级别:致命,描述:错误证书)
    • Well, yeah, there was no certificate sent. 嗯,是的,没有发送证书。

My binding is set up as follows: 我的绑定设置如下:

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

My behavior is set up as follows: 我的行为设置如下:

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

My endpoint is set up to use both the binding and the behavior. 我的端点设置为同时使用绑定和行为。 Why does WCF refuse to send the certificate when it creates the https connection? 为什么WCF在创建https连接时拒绝发送证书?

I solved the problem, but I do not understand why this configuration change fixed it. 我解决了这个问题,但我不明白为什么这个配置改变了它。 I changed this line: 我更改了这一行:

<httpsTransport useDefaultWebProxy="false" />

to this: 对此:

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

and magically it started working. 并且神奇地开始工作了。 I had understood that the requireClientCertificate "knob" was for server-side, so I hadn't tried it during my wrangling. 我已经明白requireClientCertificate “knob”是服务器端的,所以我在争吵时没有尝试过。 Apparently I was wrong. 显然我错了。

There should have been a CertificateRequest from the server, naming acceptable cert types and CAs. 应该有来自服务器的CertificateRequest,命名可接受的证书类型和CA. If your certificate doesn't match those it won't be sent. 如果您的证书与那些证书不匹配,则不会发送。

It could be a problem negotiating which security protocol to use. 协商使用哪种安全协议可能是一个问题。 Specifically im thinking that the server might not like WCF trying to use TLS 1.0. 特别是我认为服务器可能不喜欢WCF尝试使用TLS 1.0。

To see if this is the case try to add the following before invoking the service 要查看是否是这种情况,请尝试在调用服务之前添加以下内容

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

This could be added either in client code or by placing it in an IEndpointBehavior 这可以在客户端代码中添加,也可以将其放在IEndpointBehavior中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM