使用Faraday调用API遭遇SSL证书验证失败问题求助
解决Faraday SSL证书验证失败问题
从你给出的错误信息certificate verify failed (unable to get local issuer certificate)来看,核心问题是Ruby的OpenSSL环境无法验证API服务器的证书链——虽然Postman能正常工作,但Postman自带了一套完整的CA信任库,而Ruby默认使用的是系统或自身配置的CA证书,两者的信任列表不一致导致了这个问题。
下面是几个针对性的解决方案,按推荐优先级排序:
1. 提供完整的证书链(最推荐)
你目前只加载了客户端证书test.crt,但API服务器的证书可能是由中间CA签发的,而Ruby的OpenSSL找不到对应的根CA证书。Postman会自动从其内置库中补充缺失的根CA,但Ruby需要你明确提供完整的证书链。
解决步骤:
- 把你的客户端证书、中间CA证书、根CA证书合并成一个PEM格式的文件(顺序是客户端证书在前,然后中间CA,最后根CA):
cat test.crt intermediate_ca.crt root_ca.crt > full_chain.crt - 在Faraday的SSL配置中添加
ca_file指定这个完整链文件:ssl_crt = File.read(Jets.root.join('certs', 'test.crt')) ssl_key = File.read(Jets.root.join('certs', 'test.key')) full_chain = Jets.root.join('certs', 'full_chain.crt') client_cert = OpenSSL::X509::Certificate.new(ssl_crt) client_key = OpenSSL::PKey.read(ssl_key) connection = Faraday.new( 'https://sandbox-api.com/', ssl: { client_cert: client_cert, client_key: client_key, verify: true, ca_file: full_chain } ) do |conn| conn.response :json, content_type: /\bjson$/ conn.use Faraday::Response::RaiseError conn.adapter Faraday.default_adapter end
2. 检查客户端密钥是否有密码保护
如果你的test.key设置了密码,那么读取密钥时需要传入密码参数,否则OpenSSL无法解析:
client_key = OpenSSL::PKey.read(ssl_key, 'your_key_password')
Postman会自动弹出密码输入框,但Ruby代码里必须明确指定。
3. 临时禁用证书验证(仅测试环境使用)
如果只是临时调试,可以暂时关闭证书验证,但绝对不能在生产环境使用,这会带来严重的安全风险:
connection = Faraday.new( 'https://sandbox-api.com/', ssl: { client_cert: client_cert, client_key: client_key, verify: false # 禁用验证 } ) do |conn| # ... 其他配置 end
4. 确认Ruby的CA证书路径
有时候Ruby的OpenSSL默认的CA证书路径不正确,可以通过以下代码查看当前配置:
puts "Default CA file: #{OpenSSL::X509::DEFAULT_CERT_FILE}" puts "Default CA dir: #{OpenSSL::X509::DEFAULT_CERT_DIR}"
如果路径指向的目录/文件不存在或不完整,可以:
- 设置环境变量
SSL_CERT_FILE指向正确的CA证书文件 - 或者在Faraday的SSL配置中指定
ca_path指向CA证书目录
内容的提问来源于stack exchange,提问作者Mateusz Urbański
相关产品推荐
相关产品推荐

