为啥在 Windows 上使用 Mechanize 访问 SSL 站点会失败,但在 Mac 上可以工作?
Posted
技术标签:
【中文标题】为啥在 Windows 上使用 Mechanize 访问 SSL 站点会失败,但在 Mac 上可以工作?【英文标题】:Why does accessing a SSL site with Mechanize on Windows fail, but on Mac work?为什么在 Windows 上使用 Mechanize 访问 SSL 站点会失败,但在 Mac 上可以工作? 【发布时间】:2012-01-23 23:24:30 【问题描述】:这是我用来连接 SSL 站点的代码。
require 'mechanize'
a = Mechanize.new
page = a.get 'https://site.com'
我正在使用 Ruby 1.9.3 和 Mechanize 2.1pre1 + 依赖项。在 Mac 上,上面的代码工作并返回页面。在运行相同版本的 Windows 7 上,它给了我以下错误:
OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3
read server certificate B: certificate verify failed
恢复到 Mechanize 2.0.1 似乎可以解决这个问题,但是我随后被 too many connections reset by peer
问题所困扰。因此,这不是一个解决方案。
我尝试过a.verify_mode = false
,但这并没有做任何事情。我读到您可以使用以下方法关闭 SSL 验证:
open(uri,:ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE)
如何在 Mechanize 中将其关闭?为什么我只在 Windows 上收到此错误?
【问题讨论】:
【参考方案1】:您可以简单地执行以下操作:
agent = Mechanize.new
agent.verify_mode = OpenSSL::SSL::VERIFY_NONE
这适用于最新版本 2.8
【讨论】:
【参考方案2】:OpenSSL 版本(用于与Net::HTTPS
建立安全连接的库)无法在您的计算机中正确找到证书链。
不幸的是,OpenSSL 永远无法使用 Windows 安装的证书存储来验证远程服务器,因此失败了。
从您的示例中,您可以这样做:
a.agent.http.verify_mode = OpenSSL::SSL::VERIFY_NONE
为了避免验证,但这远非理想(由于明确的安全问题)
我建议你下载一些证书包(比如 curl 的包):
http://curl.haxx.se/ca
并将您的代码修改为如下内容:
require "rbconfig"
require "mechanize"
a = Mechanize.new
# conditionally set certificate under Windows
# http://blog.emptyway.com/2009/11/03/proper-way-to-detect-windows-platform-in-ruby/
if RbConfig::CONFIG["host_os"] =~ /mingw|mswin/
# http://curl.haxx.se/ca
ca_path = File.expand_path "~/Tools/bin/curl-ca-bundle.crt"
a.agent.http.ca_file = ca_path
end
page = a.get "https://github.com/"
这似乎可行,Ruby 1.9.3-p0 (i386-mingw32)、Windows 7 x64 和 mechanize 2.1.pre.1
希望对您有所帮助。
【讨论】:
如果您正在测试已知主机的 SSL,则无需检查它是否有效。只要加密仍然有效?如果平台是 windows,你知道如何有条件地添加这个吗? @KassymDorsel 更新了使用平台条件的代码,希望对您有所帮助。 我在许多项目中使用了 a.agent.http.verify_mode = OpenSSL::SSL::VERIFY_NONE 但现在当我使用相同的东西时它没有效果。我仍然收到 SSL 错误OpenSSL::SSL::SSLError Exception: SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: (null)
而在其他项目中它工作正常... ruby 1.9.2 和 rails 3.2.0
这对我有用(至少是一般方法)。我知道验证根 CA 位于 /opt/local/etc/openssl/cert.pem
,因此告诉机甲使用该文件安全地解决了错误。但是谁能告诉我 Mechanize 默认使用什么证书包?据我所知,它没有使用 MacPorts openssl、OSX 钥匙串或 curl 附带的包。宝石本身似乎不包含一个。
对于机械化 v=2.7.x,self.m_agent.verify_mode = OpenSSL::SSL::VERIFY_NONE
【参考方案3】:
Luis 的回答看起来不错,但更笼统:
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
【讨论】:
您应该避免执行 VERIFY_NONE,如果您不验证对方,这首先会破坏使用 HTTPS/SSL 的目的。如果我们通过透明代理或修改过的 DNS 将您重定向到假货是真实的地方进行连接,您将永远不会知道... 是的,但是你在抓取网页时通常不会关心这些事情。 仍然出现同样的错误OpenSSL::SSL::SSLError Exception: SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: (null)
@RAJ... 不知道您正在尝试什么版本的 Mechanize,但最新版本简化了对证书的访问。请查看有关使用证书的机械化文档。
@RAJ... 我在 Ruby 1.9.3 下遇到了完全相同的神秘错误read server hello A: (null
。最后降级到 1.9.2-p290 一切正常。很奇怪。对不起,线程劫持家伙,但这是唯一的谷歌结果。以上是关于为啥在 Windows 上使用 Mechanize 访问 SSL 站点会失败,但在 Mac 上可以工作?的主要内容,如果未能解决你的问题,请参考以下文章
在 MacOS Big Sur 上使用 perl WWW:Mechanize
是否有与 Perl 的 WWW::Mechanize 等效的 PHP?