![](/img/trans.png)
[英]Ruby on Rails Net::HTTP use_ssl throws 'undefined method'
[英]Monkey patching use_ssl= method works for Net:HTTP but not for OpenURI in Ruby 1.9.3?
背景:
问题
我正在设法解决臭名昭著的问题
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
通过在我执行的每个HTTP请求中包含我的证书来出错。 为此,我猴子补丁Net::HTTP#use_ssl=
:
# lib/gem_ext/net_http.rb
require 'open-uri'
require 'net/https'
module Net
class HTTP
alias_method :original_use_ssl=, :use_ssl=
def use_ssl=(flag)
store = OpenSSL::X509::Store.new
store.set_default_paths # Auto-include the system CAs.
Dir[Rails.root + 'config/certificates/*'].each do |cert|
puts "Adding cert: #{cert}"
store.add_cert(OpenSSL::X509::Certificate.new(File.read(cert)))
end
self.cert_store = store
self.verify_mode = OpenSSL::SSL::VERIFY_PEER
self.original_use_ssl = flag
end
end
end
现在,使用Net::HTTP
执行的请求,例如:
> uri = URI.parse('https://internal-app/secure_url.json?foo=bar')
> Net::HTTP.start(uri.host, uri.port, :read_timeout => 10.minutes, :use_ssl => uri.scheme == 'https') do |http|
> http.request Net::HTTP::Get.new(uri.request_uri)
> end
Adding cert: config/certificates/cert1.cer
Adding cert: config/certificates/cert2.cer
=> #<Net::HTTPOK 200 OK readbody=true>
完美地工作。
但是,当我尝试使用OpenURI时,我认为这只是Net :: HTTP(和其他IO操作)的包装,例如:
> require 'open-uri'
> open('https://our-all/secure_url.json?foo=bar', 'r', :read_timeout => 10.minutes)
Adding cert: config/certificates/cert1.cer
Adding cert: config/certificates/cert2.cer
#<Class:0x870e2e0>: SSL_connect returned=1 errno=0 state=SSLv3 read server certi
from D:/Ruby/Ruby193/lib/ruby/1.9.1/net/http.rb:800:in `connect'
from D:/Ruby/Ruby193/lib/ruby/1.9.1/net/http.rb:800:in `block in connect
因此,我可以看到我的猴子修补方法受到攻击(“添加证书..”),但仍然出现错误。 似乎其他一些东西正在压倒它。 有任何想法吗?
谢谢
我设法提出了一个解决方案(前一段时间,所以我希望它仍然适用)。
根据我的代码中的注释,我需要对cert_store=
和“ use_ssl=
作为Net::HTTP
和OpenURI.open_http
以不同的顺序调用这些方法进行修补”,所以我们需要确保证书被一致地添加。
所以,这是我的解决方案:
module Net
class HTTP
alias_method :original_use_ssl=, :use_ssl=
def use_ssl=(flag)
store = OpenSSL::X509::Store.new
store.set_default_paths # Auto-include the system CAs.
self.cert_store = store # Now include internal certificates.
self.verify_mode = OpenSSL::SSL::VERIFY_PEER # Force verification.
self.original_use_ssl = flag
end
alias_method :original_cert_store=, :cert_store=
def cert_store=(store)
Dir[Rails.root + 'config/certificates/*'].each do |cert|
store.add_cert(OpenSSL::X509::Certificate.new(File.read(cert)))
end
self.original_cert_store = store
end
end
end
希望能有所帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.