我正在开发一个ASP.NET Web应用程序,它使用HttpWebRequest向另一个服务器发送请求。它通过HTTPS发送请求,并且远程服务器需要客户端证书。该请求在.NET应用程序中失败,显然无法发送正确的客户端证书。我am能够成功连接和发送客户端证书,如果我只是通过网络浏览器访问该URL(特别是Chrome)。.NET应用程序无法发送客户端证书 - Win 7和Win XP?
下面的代码是一个简单的复制,只有一个基本的GET请求。
var r = WebRequest.Create(url) as HttpWebRequest;
r.ClientCertificates = new X509CertificateCollection { myX509Cert };
using (var resp = r.GetResponse() as HttpWebResponse) {
...
}
我得到我们最喜欢的例外,“无法创建SSL/TLS安全通道”。通常,这些类型的问题指出了您的证书私钥的权限问题。我尝试了所有我能想到的方法来确保所有配置都正确,但也许我错过了一些东西。长话短说,远程服务器发送的TLS CertificateRequest
的列表似乎确实可以识别我的客户端证书,但我的应用程序无法响应任何客户端证书。
这里是我的设置:
- Windows 7专业版64位
- 能够重现在Visual Studio中开发服务器,ASP运行ASP.NET MVC 3/.NET 4的应用问题。在本地IIS和.NET控制台应用程序/ .NET中运行的.NET WebForms/.NET 3.5应用程序最近安装了Microsoft .NET Framework 4.5。有没有检查是否还没有这可能是一个问题
这里是我什么都试过了,和我所知道的:
- 此代码似乎正常工作的Windows XP计算机 上运行时
- 我确保将我的客户证书导入本地计算机个人证书存储,并为我自己和所有相关的IIS用户正确配置了私钥权限
- 我试图在我的机器上重新安装证书几次
- 我已确认.NET应用程序可以访问X509证书并且
HasPrivateKey
= true - 确保我的客户端证书有效。它实际上是运行此应用程序的Web服务器的SSL证书
- 我在请求对象中设置了
PreAuthenticate = true
。没有所作为 - 我试着设置
ServicePointManager.Expect100Continue = false
,没有有所作为 - 我试着设置
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3
,但显然在远程服务器需要TLS所以这不是帮助 - 我设置了
ServicePointManager.ServerCertificateValidationCallback
委托总是返回true。但是请求在TLS握手的早期失败,甚至在它调用该代理之前就失败了 - 当我在Chrome中访问URL时,它要求我提供客户端证书,并提供正确的客户端证书作为选择,我选择该证书并获得有效答复。当我在Fiddler中构造一个请求时也可以正常工作。所以这绝对是我的.NET代码特别是问题,而不是证书本身或远程服务器等。
- 我正在使用的供应商在不同的远程服务器上设置了相同的服务,并且该服务需要不同的客户端证书。于是,我试着用不同的URL和客户端证书同样的事情,得到了相同的故障
我加入System.Net trace看到这一点:
SecureChannel#26717201 - 我们有用户提供的证书。服务器已经指定了6个发行者。寻找符合任何发行人的证书。
SecureChannel#26717201 - 留下0个客户端证书可供选择。
...
的InitializeSecurityContext(在缓冲器计数= 2,输出缓冲器长度= 0,返回代码= CertUnknown)。
我启用了全SCHANNEL logging,看到这样的警告:
远程服务器请求SSL客户端身份验证,但是没有合适的客户端证书可能被发现。将尝试匿名连接。此SSL连接请求可能成功或失败,具体取决于服务器的策略设置。
我跑Wireshark的,看见远程服务器发送一个CertificateRequest
,它似乎有一个Distinguished Name
条目以准确说明我的客户端证书的CN \ OU \ O值。之后,我的应用程序发送一个证书响应,没有证书。
似乎我错过了设置此证书以便在Windows 7中与.NET应用程序一起正常工作的事情。我最好猜测的是,与XP机器相比,我的新Windows 7机器上有不同的东西现在造成这个失败。我目前无法访问Windows XP环境来确认这一点;我会在几天内,但真的想尽快解决这个问题。
任何想法,将不胜感激。谢谢!
编辑如上所述,当在Chrome中连接到URL时,浏览器要求我提供客户端证书,并且我可以提供正确的证书并成功连接。但是,我无法在Internet Explorer(9)中成功完成此操作。我只是得到“Internet Explorer无法显示网页”,没有其他提示或解释。我被告知这可能是相关的,因为WebRequest.Create
与IE有类似的行为。我正在研究这可能意味着什么,但会重视对此的任何想法。
编辑此外,我应该注意到,远程服务器使用自签名的SSL证书。我原本以为这可能是问题所在,因此我将该证书添加为MMC中的受信任根,以便证书在我的计算机上显示为有效。这并没有解决问题。
证书是否包含“客户端验证(1.3.6.1.5.5.7.3.2)”增强型密钥用法扩展?如果没有,Chrome可能会被淘汰,因此被选中。 – 2012-03-26 13:45:47
事实证明,客户端证书没有这个增强型密钥用法扩展。我很确定这段代码在过去指向不同的远程URL和不同的客户端证书时正常工作,即使该客户端证书没有客户端验证增强密钥用法。这给了我一个调查的途径,但谢谢。 – 2012-03-26 13:58:11
其实达米安,我错了 - 所有这些证书都包括客户端身份验证增强密钥使用扩展。 – 2012-03-26 15:43:32