我正在开发一个在两个后端服务器之间使用一些HTTP通信的项目.服务器使用X509证书进行身份验证.不用说,当服务器A(客户端)建立与服务器B(服务器)的连接时,存在SSL/TLS验证错误,因为使用的证书不是来自受信任的第三方权限.
通常,处理它的方法是使用ServicePointManager.ServerCertificateValidationCallback
,例如:
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, error) => { return cert.GetCertHashString() == "xxxxxxxxxxxxxxxx"; };
这种方法有效,除非它不理想.它本质上做的是覆盖应用程序完成的每个http请求的验证过程.因此,如果另一个类将尝试运行HTTP请求,它将失败.此外,如果另一个类ServicePointManager.ServerCertificateValidationCallback
为了自己的目的而覆盖,那么我的通信开始突然失败.
想到的唯一解决方案是创建一个单独的AppDomain来执行客户端HTTP请求.这可行,但实际上 - 只有这样才能执行HTTP请求是愚蠢的.开销将是惊人的.
考虑到这一点,是否有人研究过.NET中是否有更好的实践,这将允许访问Web服务,同时处理客户端SSL/TLS验证而不影响其他Web客户端?
此方案的直接方法应该是在客户端计算机上的受信任根存储中安装两个自生成的证书.执行此操作时,您将收到安全警告,因为无法使用Thawte或类似程序对证书进行身份验证,但在此之后应进行常规安全通信.IIRC,您需要在受信任的根目录中安装完整(公钥和私钥)版本才能使用.
不使用HttpWebRequest的代码的替代方案,以及无法在证书存储中安装可信证书的环境:检查回调的错误参数,该参数将包含在回调之前检测到的任何错误.这样,您可以忽略特定哈希字符串的错误,但仍接受通过验证的其他证书.
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, error) => { if (cert.GetCertHashString() == "xxxxxxxxxxxxxxxx") { return true; } else { return error == SslPolicyErrors.None; } };
参考:https: //msdn.microsoft.com/en-us/library/system.net.security.remotecertificatevalidationcallback(v=vs.110).aspx
请注意,这仍将影响同一appdomain中的其他Web客户端实例(它们都将接受指定的哈希字符串),但至少它不会阻止其他证书.
在.NET 4.5+中使用的可接受(安全)方法是使用.在特定的请求实例上分配该回调将仅针对请求更改验证逻辑,而不会影响其他请求.HttpWebRequest.ServerCertificateValidationCallback
var request = (HttpWebRequest)WebRequest.Create("https://..."); request.ServerCertificateValidationCallback += (sender, cert, chain, error) => { return cert.GetCertHashString() == "xxxxxxxxxxxxxxxx"; };