OpenUri导致401未经授权的错误与HTTPS URL

问题描述:

我正在添加的功能,从需要使用HTTPS连接进行身份验证的来源的XML页面。我正在尝试使用Ryan Bates的Railscast#190解决方案,但我遇到401身份验证错误。OpenUri导致401未经授权的错误与HTTPS URL

这里是我的测试Ruby脚本:

require 'rubygems' 
require 'nokogiri' 
require 'open-uri' 

url = "https://biblesearch.americanbible.org/passages.xml?q[]=john+3:1-5&version=KJV" 
doc = Nokogiri::XML(open(url, :http_basic_authentication => ['username' ,'password'])) 
puts doc.xpath("//text_preview") 

这里是控制台输出I运行我的脚本后:

/usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/net/http.rb:799:in `connect': SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (OpenSSL::SSL::SSLError) 
from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/net/http.rb:799:in `block in connect' 
from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/timeout.rb:54:in `timeout' 
from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/timeout.rb:99:in `timeout' 
from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/net/http.rb:799:in `connect' 
from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/net/http.rb:755:in `do_start' 
from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/net/http.rb:744:in `start' 
from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/open-uri.rb:306:in `open_http' 
from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/open-uri.rb:775:in `buffer_open' 
from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/open-uri.rb:203:in `block in open_loop' 
from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/open-uri.rb:201:in `catch' 
from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/open-uri.rb:201:in `open_loop' 
from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/open-uri.rb:146:in `open_uri' 
from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/open-uri.rb:677:in `open' 
from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/open-uri.rb:33:in `open' 
from scrape.rb:6:in `<main>' 

在我的研究,我看到了一个帖子中,它是建议在1.9.3中可以使用以下选项:

doc = Nokogiri::XML(open(url, :http_basic_authentication => ['username' ,'password'], :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE)) 

但是,这并没有工作eit她的。我希望对解决这一挑战有所洞察。

+0

小心使用':ssl_verify_mode => OpenSSL的:: SSL :: VERIFY_NONE'。这会禁用SSL证书检查,以确保连接的完整性,从而帮助避免中间人攻击。 –

给定的URL将被重定向到/v1/KJV/passages.xml?q[]=john+3%3A1-5与HTTP状态代码302 Found。 OpenURI理解重定向,但出于安全原因自动删除身份验证头(可能)。 (*)

如果您直接访问"http://biblesearch.americanbible.org/v1/KJV/passages.xml?q[]=john+3%3A1-5",您将获得预期结果。 :-)

(*)您可以在open-uri.rb发现:

if redirect 
    ### snip ### 
    if options.include? :http_basic_authentication 
    # send authentication only for the URI directly specified. 
    options = options.dup 
    options.delete :http_basic_authentication 
    end 
+0

如果我没有记错,当重定向从安全URL到非安全URL时,必须删除安全头。这是几年前发现的漏洞或漏洞,并且不仅仅是OpenURI,而是固定在客户端。它应该由OpenURI自动处理。 –

+0

即使从HTTPS重定向到HTTPS **,从ruby 1.9.3p286(最新的稳定版本)开始,基本身份验证标头将被删除**。查看open-uri.rb了解详细信息。 – yasu

+0

谢谢@高田康之!我现在看到,只读不需要认证,只有RESTful写作。指向您指定的URL现在可以正常工作。我很感激帮助。 –

你说你需要使用HTTPS,但您使用的HTTP协议:

url = "http://biblesearch...." 

OpenURI理解HTTP和HTTPS。如果你想使用HTTPS连接,在URL中的协议更改为HTTPS,然后进行连接:

url = "https://biblesearch...." 
+0

是的,对不起。我更新了代码和输出。看来现在有一个验证证书的问题。研究... –

你可以做到这一点,它应该工作太:

open(url, :http_basic_authentication => [user, pass]) doc = Nokogiri::HTML(open(url, :http_basic_authentication => [user, pass]))

然后,您可以解析文档反正你想。 通过在第二个请求中再次通过头中的http_basic_authentication,您将弥补第一个请求中删除的头。 希望这对你有用。

http://http-basic-authentication-nokogiri.blogspot.com/2014/08/http-basic-authentication-using-nokogiri.html