2

我正在运行一个 ruby​​ on rails 应用程序(rails 4.x),我有一个受保护的资源,需要使用客户端证书进行身份验证。我需要强制客户端使用其证书进行身份验证。这甚至可以通过 Rails 控制器实现,还是在具有我的服务器证书的上层处理?

我可以从 rails 向另一台服务器发出请求,并使用我的 rails 证书进行身份验证,但是反过来似乎是不可能的。

这就是我从我的 rails 应用程序向另一台服务器进行身份验证的方式

# Example usage:
req = HttpsReq.new
response = req.http.request Net::HTTP::Get.new "/api/users"
require 'openssl'
require 'net/http'
require 'json'

class HttpsReq

  DEFAULT_OPTIONS = {
    use_ssl: true,
    verify_mode: OpenSSL::SSL::VERIFY_PEER,
    keep_alive_timeout: 30,
    ssl_version: :TLSv1_2,
    ca_file: File.join(File.dirname(__FILE__), "cacert.pem"),
    cert: OpenSSL::X509::Certificate.new(Base64.decode64(ENV['CLIENT_CERT_PEM'])),
    key: OpenSSL::PKey::RSA.new(Base64.decode64(ENV['CLIENT_KEY_PEM']), ENV['CLIENT_KEY_PASSWORD'])
  }

  def initialize(http = nil)
    if http
      @http = http
    else
      @http = Net::HTTP.start(ENV['SECURE_SERVER'], 8080, DEFAULT_OPTIONS)
    end
  end

end
4

1 回答 1

2

这是可能的,但你需要做一些技巧。因为只能在 TLS 握手过程中获取客户端证书。

我认为大多数 Rails Web 应用程序设计为在代理服务器或负载平衡器后面运行。在 Web 请求到达 Rails 控制器之前,这种情况下的 TLS 握手过程已经完成。

因此,您可以使用几种技巧。

  1. 使用 Ruby HTTP 客户端运行单独的端点并提供所有必需的根证书和私钥。从 rails 控制器,您需要强制重定向到该 Ruby HTTP 客户端的端点,直到您的客户端(浏览器)成功通过客户端证书进行身份验证。
  2. 配置需要相互 TLS 身份验证的 NGINX,然后将实际的原始客户端证书从 HTTP 请求传递到 Rails 控制器。因此,通过这种方式,您需要为 Nginx 配置设置特殊 url 或特殊端口,并且您需要从 Rails 控制器强制重定向该端点。这个特殊的端点可以用 HTTP 参数 ( X-SSL-CERT $ssl_client_raw_cert) 代理你的实际 Rails 控制器。因此,您可以从那里读取实际的客户端证书并使用 Ruby OpenSSL 库对其进行验证。

如果您需要更多信息,请查看这篇文章

于 2020-07-17T04:15:19.567 回答