我正在开发一个使用HttpWebRequest向另一个服务器发送请求的ASP.NET web应用程序。它通过HTTPS发送请求,而远程服务器需要客户端证书。请求在.NET应用程序中失败,显然无法发送正确的客户端证书。如果我只是用web浏览器(特别是Chrome)访问url,我就能够成功地连接并发送客户端证书。
下面的代码是一个简单的复制品,只有一个基本的GET请求。
var r = WebRequest.Create(url) as HttpWebRequest;
r.ClientCertificates = new X509CertificateCollection { myX509Cert };
using (var resp = r.GetResponse() as HttpWebResponse) {
...
}
我得到了我们最喜欢的异常,“无法创建SSL/TLS安全通道”。通常,这些类型的问题指向证书的私钥上的权限问题。我尝试了我能想到的所有方法来确保这些配置都是正确的,但我可能遗漏了一些东西。长话短说,远程服务器正在发送一个带有列表的TLS CertificateRequest
,该列表似乎确实正确地标识了我的客户端证书,但我的应用程序无法使用任何客户端证书进行响应。
下面是我的设置:
这是我尝试过的一切,以及我所知道的:
HasPrivateKey
=true< code >H219PreAuthenticate = true
。我试着设置ServicePointManager.Expect100Continue = false
,ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3
,但是显然远程服务器需要TLS,所以这对ServicePointManager.ServerCertificateValidationCallback
委托,让它总是返回true。但是请求在TLS握手之前失败了,在它甚至到达调用这个delegate我添加了System.Net trace,并看到了以下内容:
SecureChannel#26717201 -我们有用户提供的证书。服务器已指定6个颁发者。查找与任何颁发者匹配的证书。
SecureChannel#26717201 -剩下0个客户端证书可供选择。
..。
InitializeSecurityContext(入缓冲区count=2,出缓冲区length=0,返回的code=CertUnknown)。
我启用了完整的SCHANNEL logging,并看到以下警告:
远程服务器已请求SSL客户端身份验证,但找不到合适的客户端证书。将尝试匿名连接。此SSL连接请求可能成功,也可能失败,具体取决于服务器的策略设置。
我运行Wireshark,看到远程服务器发送了一个CertificateRequest
,它似乎有一个Distinguished Name
条目,其中包含我的客户端证书的CN\OU\O值。在那之后,我的应用程序发送一个不带证书的证书响应。
在设置此证书以在Windows7中与.NET应用程序正常工作时,我似乎遗漏了一些东西。我最好的猜测是,与XP机器相比,我的新Windows7机器上有一些不同的东西,导致现在失败。我目前无法访问Windows XP环境来确认这一点;我会在几天后确认,但我真的希望尽快解决这一问题。
任何想法都将不胜感激。谢谢!
编辑如上所述,当在Chrome中连接到URL时,浏览器要求我提供客户端证书,我可以提供正确的证书并成功连接。但是,我无法在Internet Explorer (9)中成功完成此操作。我只是看到"Internet Explorer无法显示网页“,没有其他提示或解释。有人告诉我,这可能是相关的,因为WebRequest.Create
的行为与IE相似。我正在研究这可能意味着什么,但我会重视这方面的任何想法。
编辑另外,我应该注意到远程服务器使用自签名的SSL证书。我最初认为这可能是问题所在,所以我将证书添加为MMC中的受信任根,以便证书在我的计算机上显示为有效。这并没有解决问题。
发布于 2012-03-27 20:33:17
这被证明是一个相当简单的问题,但它很难被发现。我的应用程序将我的客户端证书放在其keystore中的远程服务器,而不是我的客户端证书信任链中的任何根证书。
我能够使用我的代码成功地向另一台需要客户端证书的服务器发送请求。在发送这个成功的请求时,我在Wireshark中捕获了一个,在将失败的请求发送到另一个服务器时,我也捕获了一个。在Wireshark捕获中,我找到了"Server Hello“,并比较了从远程服务器发送的消息。"good“远程服务器正在发送我的客户端证书以及该消息的"Certificate Request”部分中的根证书。“坏”的远程服务器只发送我的客户端证书。
这使我想起System.Net诊断跟踪为“服务器已指定6个颁发者...剩下0个客户端证书可供选择”。因此,“发行者”是这里的关键术语。最初很容易忽略这一点,因为在我对TLS握手的初始分析中,服务器在证书请求中向我的客户端发送证书。事后看来,服务器应该发送根证书,而不是客户端证书本身,这是有意义的。
发布于 2013-10-22 02:47:22
我想为这个问题添加另一个“解决方案”。
如果列表太长,服务器可能无法发送正确的颁发者列表。这似乎是微软的一个限制。http://support.microsoft.com/kb/933430
来源:http://netsekure.org/2011/04/tls-client-authentication-and-trusted-issuers-list/
解决方案是要求服务器根本不发送列表。(通过编辑注册表值)
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL
取值名称:False取值类型: REG_DWORD取值数据:0( SendTrustedIssuerList )
发布于 2016-08-30 23:10:01
对我来说,这些确切的症状是由使用TLS 1.0引起的,这是服务器不允许的。这可以在跟踪日志中找到:
密钥信息:0: ProcessAuthentication(Protocol=Tls,System.Net 168位强度,Hash=Sha1 160位强度,密钥Exchange=RsaKeyX 2048位强度)。
TLS1.0是.NET 4.5的默认值,但可以通过设置来覆盖它:
ServicePointManager.SecurityProtocol =
SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
还有一些some registry flags允许在不更改现有代码的情况下对其进行设置。
https://stackoverflow.com/questions/9858275
复制相似问题