带有ca认证的Ruby https在使用curl时不起作用

时间:2016-03-23 10:04:08

标签: ruby ssl certificate ssl-certificate net-http

在ruby中,我尝试与我在本地设置的nginx服务器进行ssl连接,并使用自动签名证书。我的代码是:

require "net/http"
require "net/https"
require "openssl"
require "uri"
require "pp"

request = Net::HTTP::Get.new("/")
response = Net::HTTP.start(
  "localhost",
  443,
  {
    :use_ssl => true,
    :key => OpenSSL::PKey::RSA.new(File.read("/home/gg/crt/client.key")),
    :cert => OpenSSL::X509::Certificate.new(File.read("/home/gg/crt/client.crt")),
    :ca_file => "/home/gg/crt/ca.pem",
    :verify_mode => OpenSSL::SSL::VERIFY_PEER,
    :verify_depth => 5,
  }
) do |http|
      http.request(request)
end
puts response.inspect
puts response.body

当我运行它时返回

/home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:923:in `connect': SSL_connect returned=1 errno=0 state=error: certificate verify failed (OpenSSL::SSL::SSLError)
    from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:923:in `block in connect'
    from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/timeout.rb:74:in `timeout'
    from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:923:in `connect'
    from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:863:in `do_start'
    from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:852:in `start'
    from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:583:in `start'
    from testso.rb:8:in `<main>'

但如果我用curl运行它,我得到了正确的结果:

curl https://localhost --key crt/client.key --cert crt/client.crt --cacert crt/ca.pem

我做错了什么?

2 个答案:

答案 0 :(得分:0)

我感到愚蠢,但想出了问题。

生成不同的证书时,我将某些字段留空。 似乎openssl检测到这个证书是&#34;看起来&#34; autosigned。

因此,如果我们使用OpenSSL :: SSL :: VERIFY_PEER,则连接失败

因此,为了确保使用CA可以很好地生成证书: openssl verify -CAfile ca.crt server.crt (和client.crt的命令相同)

如果我们得到

error 18 at 0 depth lookup:self signed certificate
OK

证书被检测为自动签名且失败

如果我们得到

 Signature ok

应该有效

答案 1 :(得分:0)

为了帮助他人,这里有一个使用Ruby 2.0的工作解决方案,用于HTTP GET。

require "net/http"

uri = URI.parse('https://your_url.com')
http = Net::HTTP.new(uri.host, uri.port)
OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ssl_version]=nil
http.use_ssl = true
http.ca_path='/etc/pki/tls/certs/'
http.ca_file='/etc/pki/tls/certs/YOUR_CERT_CHAIN_FILE'
http.cert = OpenSSL::X509::Certificate.new(File.read("YOUR_CERT)_FILE"))
http.key = OpenSSL::PKey::RSA.new(File.read("YOUR_KEY_FILE"))

#SSLv3 is cracked, and often not allowed
http.ssl_version = :TLSv1_2

#### This is IMPORTANT
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

#Crete the GET request
request = Net::HTTP::Get.new(uri.request_uri)
#Add Headers, if needed
request.add_field 'X_REMOTE_USER', 'USER_NAME'
request.add_field 'Accept', '*'

#Get Response
response = http.request(request)

#Review Response
puts response.body