为啥在 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

如何在Windows上安装Python包?

Python Mechanize 选择一个没有名字的表单

是否有与 Perl 的 WWW::Mechanize 等效的 PHP?

在 python 中使用 mechanize 剥离 html 标签并仅返回文本

Python使用mechanize模拟浏览器