将自签名证书与 .NET 的 HttpWebRequest/Response 一起使用
我正在尝试连接到使用自签名 SSL 证书的 API。 我使用 .NET 的 HttpWebRequest 和 HttpWebResponse 对象来执行此操作。 我得到一个例外:
底层连接已关闭:无法建立 SSL/TLS 安全通道的信任关系。
我明白这意味着什么。 我理解为什么 .NET 认为它应该警告我并关闭连接。 但在这种情况下,我只想连接到 API,不管中间人攻击如何。
那么,我该如何为这个自签名证书添加例外呢? 或者是告诉 HttpWebRequest/Response 根本不验证证书的方法? 我该怎么做呢?
I'm trying to connect to an API that uses a self-signed SSL certificate. I'm doing so using .NET's HttpWebRequest and HttpWebResponse objects. And I'm getting an exception that:
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
I understand what this means. And I understand why .NET feels it should warn me and close the connection. But in this case, I'd like to just connect to the API anyway, man-in-the-middle attacks be damned.
So, how do I go about adding an exception for this self-signed certificate? Or is the approach to tell HttpWebRequest/Response not to validate the certificate at all? How would I do that?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
事实证明,如果您只想完全禁用证书验证,则可以更改 ServicePointManager 上的 ServerCertificateValidationCallback,如下所示:
这将验证所有证书(包括无效、过期或自签名的证书)。
Turns out, if you just want to disable certificate validation altogether, you can change the ServerCertificateValidationCallback on the ServicePointManager, like so:
This will validate all certificates (including invalid, expired or self-signed ones).
@Domster:这可行,但您可能希望通过检查证书哈希是否与您的期望相匹配来强制执行一些安全性。 因此,扩展版本看起来有点像这样(基于我们正在使用的一些实时代码):
@Domster: that works, but you might want to enforce a bit of security by checking if the certificate hash matches what you expect. So an expanded version looks a bit like this (based on some live code we're using):
您可以覆盖每个 HttpWebRequest 本身的 SSL 验证(而不是通过影响所有请求的全局委托):
请注意,在 .NET 4.5 中, net.httpwebrequest.servercertificatevalidationcallback.aspx" rel="noreferrer">http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.servercertificatevalidationcallback.aspx
Note, that in .NET 4.5 you can override SSL validation per HttpWebRequest itself (and not via global delegate which affects all requests):
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.servercertificatevalidationcallback.aspx
将自签名证书添加到本地计算机受信任的根证书颁发机构
您可以通过以管理员身份运行 MMC 来导入证书。
如何:使用 MMC 管理单元查看证书
Add the self signed cert to the Local Computer Trusted Root Certification Authorities
You can import the cert by running the MMC as Administrator.
How to: View Certificates with the MMC Snap-in
Domster 的回答中使用的验证回调的范围可以使用
上的 sender 参数限制为特定请求ServerCertificateValidationCallback 委托。 以下简单的作用域类使用此技术临时连接仅针对给定请求对象执行的验证回调。
上面的类可用于忽略特定请求的所有证书错误,如下所示:
The scope of the validation callback used in Domster's answer can be limited to a specific request using the sender parameter on the
ServerCertificateValidationCallback
delegate. The following simple scope class uses this technique to temporarily wire up a validation callback that only executes for a given request object.The above class can be used to ignore all certificate errors for a specific request as follows:
只是以 devstuff 的答案为基础,包括主题和发行者...欢迎评论...
Just building on answer from devstuff to include subject and issuer...comments welcome...
添加作为对其他人的可能帮助...如果您希望它提示用户安装自签名证书,您可以使用此代码(从上面修改)。
不需要管理员权限,安装到本地用户信任的配置文件:
这似乎对我们的应用程序很有效,如果用户按否,通信将无法进行。
更新:2015-12-11 - 将 StoreName.Root 更改为 StoreName.My - My 将安装到本地用户存储中,而不是 Root。 即使您“以管理员身份运行”,在某些系统上 root 也无法工作
To add as a possible help to someone else... If you want it to prompt the user to install the self-signed cert, you can use this code (modified from above).
Does not require admin rights, installs to the local users trusted profiles:
This seems to work well for our application, and if the user presses no, the communication will not work.
Update: 2015-12-11 - Changed StoreName.Root to StoreName.My - My will install into the local users store, instead of Root. Root on some systems will not work, even if you "run as administrator"
首先 - 我很抱歉,因为我已经使用了@devstuff 描述的解决方案。 不过,我找到了一些改进的方法。
这是我的修改:
设置证书:
传递委托方法
client.pfx
是使用 KEY 和 CERT 生成的,如下所示:First of all - I apologize, because I have used the solution that was described by @devstuff. However, I have found some ways to improve it.
Here is my modification:
setting certificates:
passing delegate method
client.pfx
is generated with KEY and CERT as such:要记住的一件事是,拥有 ServicePointManager.ServerCertificateValidationCallback 似乎并不意味着 CRL 检查和服务器名称验证未完成,它仅提供了一种覆盖其结果的方法。 因此,您的服务可能仍需要一段时间才能获得 CRL,之后您才会知道它未通过某些检查。
One thing to keep in mind is that having the ServicePointManager.ServerCertificateValidationCallback does not seem to mean that the CRL check and servername validation are not done, it only provides a means to override their result. So your service might still take a while to get a CRL, you'll only know afterwards that it failed some checks.
我遇到了与OP相同的问题,其中网络请求会抛出确切的异常。 我认为所有设置都正确,证书已安装,我可以很好地在机器存储中找到它并将其附加到 Web 请求,并且我已禁用请求上下文中的证书验证。
事实证明,我正在我的用户帐户下运行,并且证书已安装到机器存储中。 这导致 Web 请求抛出此异常。 为了解决这个问题,我必须以管理员身份运行或将证书安装到用户存储并从那里读取它。
看起来 C# 能够在机器存储中找到证书,即使它不能与 Web 请求一起使用,这会导致在发出 Web 请求后引发 OP 的异常。
I was running into the same problem as the OP where the web request would throw that exact exception. I had everything setup correctly I thought, the certificate was installed, I could locate it in the machine store just fine and attach it to the web request, and I had disabled the verification of certificates on the request context.
It turned out that I was running under my user account, and that the certificate was installed to the machine store. This caused the web request to throw this exception. To solve the problem I had to either be running as administrator or install the certificate to the user store and read it from there.
It would seem that C# is able to find the certificate in the machine store even though it can't be used with a web request, and that this results in the OP's exception being thrown once the web request is issued.