我跟着Railscast #235尝试设置最小的Facebook身份验证。
我首先建立了一个Twitter身份验证,就像Ryan本人所做的那样。这完美无瑕。
然后我继续添加Facebook登录。但是,在授权应用程序后,重定向到/auth/facebook/callback
失败并显示:
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
我正在使用localhost。我没有在应用程序中设置任何SSL。我做错了什么?
答案 0 :(得分:74)
真正的问题是法拉第(Omniauth / Oauth用于他们的HTTP调用)不是没有为OpenSSL设置ca_path变量。至少在Ubuntu上,大多数根证书都存储在“/ etc / ssl / certs”中。由于法拉第不是未设置此变量(并且目前没有这样做的方法),OpenSSL 不是 wasn找不到Facebook的SSL证书的根证书。
我submitted a pull request to Faraday这将增加对此变量的支持,希望他们很快就能完成此更改。在此之前,您可以将法拉第monkeypatch看作this或使用my fork of Faraday。之后,您应该在Gemspec中指定版本0.3.0的OAuth2 gem,它支持将SSL选项传递给法拉第。您现在需要做的就是升级到Faraday 0.6.1,它支持传递ca_path变量并升级到OmniAuth 0.2.2,它具有适用于OAuth2的依赖项。然后,您只需将以下内容添加到Omniauth初始值设定项中即可正确解决此问题:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, FACEBOOK_KEY, FACEBOOK_SECRET, {:client_options => {:ssl => {:ca_path => "/etc/ssl/certs"}}}
end
所以,回顾一下:
希望Faraday和Omniauth的下一版本都将采用这种解决方案。
感谢上面的KirylP让我走上了正确的道路。
答案 1 :(得分:18)
我遇到了这个问题并尝试使用:ca_path参数但没有成功。在浏览了Github一段时间之后,我发现了一个建议,提到使用:ca_file并直接指向认证。
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, 'secret_key', 'secret_key',
:client_options => {:ssl => {:ca_file => '/etc/pki/tls/certs/ca-bundle.crt'}}}
end
如果您需要获取系统认证文件(以及使用Linux)的路径,只需从终端输入即可。这将为您提供有关SSL设置的大量信息,包括路径(请参阅OPENSSLDIR)。您需要将certs / ca-bundle.crt添加到提供的路径中。
open-ssl version -a
答案 2 :(得分:13)
我在ubuntu 10.10(Maverick)...在我开始工作前大约6个小时挣扎,分享我的经验
让它发挥作用的唯一因素是(感谢Alex)
if Rails.env.development?
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
end
答案 3 :(得分:7)
管理必须通过SSL证书验证。 我的项目使用37signals ID进行Basecamp集成(Ruby 1.9.2-p130,Rails 3.0.4)。
<强> RAILS_ROOT /配置/初始化/ omniauth.rb 强>:
require 'omniauth/oauth'
Rails.application.config.middleware.use OmniAuth::Strategies::ThirtySevenSignals,
'CLIENT_ID', 'CLIENT_SECRET', {client_options: {ssl: {ca_file: Rails.root.join('gd_bundle.crt').to_s}}}
module OAuth2
class Client
def initialize(client_id, client_secret, opts = {})
adapter = opts.delete(:adapter)
self.id = client_id
self.secret = client_secret
self.site = opts.delete(:site) if opts[:site]
self.options = opts
self.connection = Faraday::Connection.new(site, {ssl: opts.delete(:ssl)})
self.json = opts.delete(:parse_json) # ^ my code starts here
if adapter && adapter != :test
connection.build { |b| b.adapter(adapter) }
end
end
end
end
您可以从37signals.com获取'CLIENT_ID','CLIENT_SECRET',并从GoDaddy获取证书捆绑文件 gd_bundle.crt ,因为37signals正在使用其CA.
答案 4 :(得分:6)
如果要部署到Heroku,则需要指向特定的文件位置。这适用于我(在config / initializers / omniauth.rb中):
Rails.application.config.middleware.use OmniAuth::Builder do
# This cert location is only for Heroku
provider :facebook, APP_ID, APP_SECRET, {:client_options => {:ssl => {:ca_file => "/usr/lib/ssl/certs/ca-certificates.crt"}}}
end
答案 5 :(得分:5)
我使用来自http://certifie.com/ca-bundle/
的CA捆绑解决了这个问题在我的Devise初始化程序中:
:client_options => { :ssl => { :ca_file => "#{Rails.root}/config/ca-bundle.crt" } } }
答案 6 :(得分:4)
所有解决方案对我都没有用,然后我发现了这个
http://railsapps.github.io/openssl-certificate-verify-failed.html
rvm osx-ssl-certs update all
osx 10.8 ruby 2.0.0 via rvm
答案 7 :(得分:4)
看起来Omniauth现在使用了更新版本的法拉第,这解释了为什么上面的猴子补丁不适合我。我同意必须有更好的方法,但对于其他只需要让它进行测试的人来说,这是一个更新版本:
(使用以下代码在initializers目录中创建一个文件)
require 'faraday'
module Faraday
class Adapter
class NetHttp < Faraday::Adapter
def call(env)
super
url = env[:url]
req = env[:request]
http = net_http_class(env).new(url.host, url.inferred_port)
if http.use_ssl = (url.scheme == 'https' && env[:ssl])
ssl = env[:ssl]
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.cert = ssl[:client_cert] if ssl[:client_cert]
http.key = ssl[:client_key] if ssl[:client_key]
http.ca_file = ssl[:ca_file] if ssl[:ca_file]
http.cert_store = ssl[:cert_store] if ssl[:cert_store]
end
http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout]
http.open_timeout = req[:open_timeout] if req[:open_timeout]
if :get != env[:method]
http_request = Net::HTTPGenericRequest.new \
env[:method].to_s.upcase, # request method
!!env[:body], # is there data
true, # does net/http love you, true or false?
url.request_uri, # request uri path
env[:request_headers] # request headers
if env[:body].respond_to?(:read)
http_request.body_stream = env[:body]
env[:body] = nil
end
end
begin
http_response = if :get == env[:method]
# prefer `get` to `request` because the former handles gzip (ruby 1.9)
http.get url.request_uri, env[:request_headers]
else
http.request http_request, env[:body]
end
rescue Errno::ECONNREFUSED
raise Error::ConnectionFailed, $!
end
http_response.each_header do |key, value|
response_headers(env)[key] = value
end
env.update :status => http_response.code.to_i, :body => http_response.body
@app.call env
end
end
end
end
答案 8 :(得分:2)
我正在使用Faraday 0.6.1和OAUTH2(单独使用,不包含任何东西)。这足以解决我的问题(在Gentoo上,应该在Ubunto上工作)
转过来
client = OAuth2::Client.new(FACEBOOK_API_KEY, FACEBOOK_API_SECRET, :site => FACEBOOK_API_SITE)
进入这个
client = OAuth2::Client.new(FACEBOOK_API_KEY, FACEBOOK_API_SECRET, :site => FACEBOOK_API_SITE, :ssl => {:ca_path => '/etc/ssl/certs' })
答案 9 :(得分:2)
编辑:检查以下答案,因为它更相关
这对我有用(修复由https://github.com/jspooner提供):
使用以下猴子补丁在初始化程序的目录中创建一个文件:
require 'faraday'
module Faraday
class Adapter
class NetHttp < Faraday::Adapter
def call(env)
super
is_ssl = env[:url].scheme == 'https'
http = net_http_class(env).new(env[:url].host, env[:url].port || (is_ssl ? 443 : 80))
if http.use_ssl = is_ssl
ssl = env[:ssl]
if ssl[:verify] == false
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
else
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # <= PATCH or HACK ssl[:verify]
end
http.cert = ssl[:client_cert] if ssl[:client_cert]
http.key = ssl[:client_key] if ssl[:client_key]
http.ca_file = ssl[:ca_file] if ssl[:ca_file]
end
req = env[:request]
http.read_timeout = net.open_timeout = req[:timeout] if req[:timeout]
http.open_timeout = req[:open_timeout] if req[:open_timeout]
full_path = full_path_for(env[:url].path, env[:url].query, env[:url].fragment)
http_req = Net::HTTPGenericRequest.new(
env[:method].to_s.upcase, # request method
(env[:body] ? true : false), # is there data
true, # does net/http love you, true or false?
full_path, # request uri path
env[:request_headers]) # request headers
if env[:body].respond_to?(:read)
http_req.body_stream = env[:body]
env[:body] = nil
end
http_resp = http.request http_req, env[:body]
resp_headers = {}
http_resp.each_header do |key, value|
resp_headers[key] = value
end
env.update \
:status => http_resp.code.to_i,
:response_headers => resp_headers,
:body => http_resp.body
@app.call env
rescue Errno::ECONNREFUSED
raise Error::ConnectionFailed.new(Errno::ECONNREFUSED)
end
def net_http_class(env)
if proxy = env[:request][:proxy]
Net::HTTP::Proxy(proxy[:uri].host, proxy[:uri].port, proxy[:user], proxy[:password])
else
Net::HTTP
end
end
end
end
end
答案 10 :(得分:1)
我的问题通过确保openSSL使用正确的证书目录来解决:
对于我的系统(ubuntu64),这是: ENV ['SSL_CERT_DIR'] ='/ usr / share / ca-certificates /'
这是使用jruby-openssl和JRuby 1.6.0
我刚刚将此设置添加到development.rb
答案 11 :(得分:1)
我知道这听起来微不足道,但请确保您使用的是正确的协议。我一直收到这个错误然后意识到我试图通过http连接。 1.5小时浪费是因为我是个白痴。
答案 12 :(得分:0)
如果你特意在Leopard上遇到问题,那么这就是我所做的。
我的证书很旧,需要更新。我下载了这个:
http://curl.haxx.se/ca/cacert.pem
然后替换了我在Leopard上找到的证书:
/usr/share/curl/curl-ca-bundle.crt
重新加载你正在访问它的任何东西,你应该好好去!
答案 13 :(得分:0)
仅仅因为说明对我来说有点不同,我想我加了2美分:
我在使用OS X Lion并使用macports和rvm
我安装了curl-ca-bundle:
sudo port install curl-ca-bundle
然后我将omniauth配置调整为:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, APP_CONFIG['CONSUMER_KEY'], APP_CONFIG['CONSUMER_SECRET'],
:scope => 'https://www.google.com/m8/feeds https://www.googleapis.com/auth/userinfo.profile',
:ssl => {:ca_path => "/share/curl/curl-ca-bundle.crt"}
end
答案 14 :(得分:0)
在Ubuntu上,我所要做的就是将/environments/development.rb更新为:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, FACEBOOK_KEY, FACEBOOK_SECRET, {:client_options => {:ssl => {:ca_path => "/etc/ssl/certs"}}}
end
然后:
cd /etc/ssl/certs
sudo wget http://curl.haxx.se/ca/cacert.pem
沃拉!
答案 15 :(得分:0)
我终于找到了Mountain Lion的修复程序。请参阅:http://coderwall.com/p/f4hyqw
rvm pkg install openssl
rvm reinstall 1.9.3 --with-openssl-dir=$rvm_path/usr
答案 16 :(得分:0)
我在Mountain Lion上使用RVM遇到了类似的错误。似乎Ruby无法找到授权SSL连接所需的CA证书。你需要安装一个。这个解决方案成功了:
http://fredwu.me/post/28834446907/fix-openssl-error-on-mountain-lion-and-rvm
(虽然我无法在浏览器中加载该页面,但我必须在Google缓存中找到它。)
这是简短的回答:
curl http://curl.haxx.se/ca/cacert.pem -o ~/.rvm/usr/ssl/cert.pem
你已经完成了。
答案 17 :(得分:0)
这似乎是1.9.x问题。恢复到1.8.7修复了问题。