Ruby 1.8.7 和 Net::HTTP:使用客户端证书发出 SSL GET 请求?

标签 ruby ssl certificate client-certificates net-http

我正在尝试使用 Net::HTTP 通过 SSL 获取资源。这是相关的代码片段:

req = Net::HTTP::Get.new(ContentURI.path)
https = Net::HTTP.new(ContentURI.host, ContentURI.port)
https.use_ssl = true
https.cert = OpenSSL::X509::Certificate.new(@cert_raw)
https.key = OpenSSL::PKey::RSA.new(@cert_key_raw)
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
https.ca_file = File.join(TestDataPath, 'cacert.pem')
resp = https.start { |cx| cx.request(req) }

或替换最后一行:

resp = https.get(ContentURI.path)

我已验证各个位(证书、 key 、CA 证书等)都是正确的。

问题是 cx.request(req) 抛出异常:

OpenSSL::SSL::SSLError: SSL_connect SYSCALL returned=5 errno=0 state=SSLv3 read server session ticket A

服务器上的 Apache SSL 错误日志包含以下内容:

[Tue Jan 24 11:47:26 2012] [debug] ssl_engine_kernel.c(1876): OpenSSL: Loop: SSLv3 read finished A
[Tue Jan 24 11:47:26 2012] [debug] ssl_engine_kernel.c(1905): OpenSSL: Exit: error in SSLv3 write session ticket A
[Tue Jan 24 11:47:26 2012] [debug] ssl_engine_kernel.c(1905): OpenSSL: Exit: error in SSLv3 write session ticket A
[Tue Jan 24 11:47:26 2012] [info] [client 10.11.88.53] SSL handshake interrupted by system [Hint: Stop button pressed in browser?!]
[Tue Jan 24 11:47:26 2012] [info] [client 10.11.88.53] Connection closed to child 0 with abortive shutdown (server _SERVERNAME_:443

证书、 key 和 CA 证书文件通过其他工具与此 SSL 主机一起工作;我只是无法使用 Net::HTTP[S] 以编程方式重现成功。

感谢任何能指出我做错了什么的人!

最佳答案

我会说这是 Apache 设置的问题,而不是 Ruby 本身的问题。

检查一下:

$ curl https://palladium.wejn.cz/sslcerttest/
curl: (56) SSL read: error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure, errno 0
$ curl https://palladium.wejn.cz/sslcerttest/ -E client.pem
<pre>Yop.</pre>

然后:

#!/usr/bin/ruby
require 'net/http'
require 'net/https'
require 'openssl'
require 'uri'

ContentURI = URI.parse("https://palladium.wejn.cz/sslcerttest/")
@cert_raw = File.read('client.pem')
@cert_key_raw = @cert_raw
TestDataPath = '.'

req = Net::HTTP::Get.new(ContentURI.path)
https = Net::HTTP.new(ContentURI.host, ContentURI.port)
https.use_ssl = true
https.cert = OpenSSL::X509::Certificate.new(@cert_raw)
https.key = OpenSSL::PKey::RSA.new(@cert_key_raw)
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
https.ca_file = File.join(TestDataPath, 'cacert.pem')
resp = https.start { |cx| cx.request(req) }
p resp
p resp.body

结果:

$ ruby a.rb
#<Net::HTTPOK 200 OK readbody=true>
"<pre>Yop.</pre>\n"

$ dpkg -l ruby1.8 | tail -n1 | awk '{print $3}'
1.8.7.302-2squeeze1

$ ruby -v
ruby 1.8.7 (2010-08-16 patchlevel 302) [x86_64-linux]

当然,有问题的 apache 配置是:

<Directory /var/www/sslcerttest/>
    SSLVerifyClient require
    SSLVerifyDepth 5
    SSLCACertificateFile /var/www/sslcerttest/cacert.pem
    SSLCACertificatePath /var/www/sslcerttest/
    SSLOptions +FakeBasicAuth
    SSLRequireSSL
    SSLRequire %{SSL_CLIENT_S_DN_O} eq "Wejn s.r.o." and %{SSL_CLIENT_S_DN_OU} eq "Server Certificate"
</Directory>

也许发布其他详细信息(要测试的 apache 配置)在跟踪此问题时会有所帮助...

关于Ruby 1.8.7 和 Net::HTTP:使用客户端证书发出 SSL GET 请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8991036/

相关文章:

ruby-on-rails - 测试与 rspec-rails 3.0.1 和 shoulda 的关联不起作用

ruby-on-rails - 检查 model.save 上对象的错误

ruby-on-rails - Rails 使用系统版本的 ruby​​ 而不是 Chruby set default

ruby - 对象应该是一种类

delphi - 如何验证服务器主机名

certificate - Windows 应用商店应用测试证书已过期

windows - 如何在未连接到 Internet 的计算机上安装 Remote Tools for Visual Studio 2015

ssl - 将自签名 ssl 证书绑定(bind)到端口失败

Python Magic(智能,双模)SSL Socket?

ios - 允许 NSBundle.mainBundle() 在 swift iOS 应用程序中查找 "der"格式的证书文件