调用第三方API报错:SSL证书强制验证的触发原因
SSL证书校验失败问题原因说明
问题现象
近期向第三方API发送请求时抛出证书验证错误,请求实现代码如下:
def api_call uri = URI.parse(url) https = Net::HTTP.new(uri.host, uri.port) https.use_ssl = true request = Net::HTTP::Post.new(uri) request.body = request_body.to_json request.content_type = 'application/json' https.request(request) end
触发的具体错误信息:OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed
已知在请求配置中添加http.ca_file = '/path/ca_file'指定CA证书路径可修复该问题,核心疑问为:
- 是什么变更导致证书验证成为必选项?
- 是否存在服务端特定的证书配置或扩展项,会强制请求发送方校验证书?
问题解答
首先明确:不存在任何服务端证书配置或扩展项,可以强制客户端开启证书校验。是否校验SSL证书完全是客户端侧的自主配置,开关控制权完全在发起请求的一方。
你遇到证书校验强制生效的问题,基本来自两类变更:
- 客户端默认配置变更
早期Ruby版本(2.0及更早版本)中,Net::HTTP库发起HTTPS请求时,verify_mode参数的默认值为OpenSSL::SSL::VERIFY_NONE,即默认不校验服务端证书合法性,直接建立连接,不会触发证书校验错误。从Ruby 2.1版本开始,官方出于安全考虑,将HTTPS请求的默认校验模式修改为OpenSSL::SSL::VERIFY_PEER,即强制校验服务端证书链的合法性,如果本地没有可信任的根CA证书完成证书链验证,就会直接抛出你看到的SSLError。
如果你近期做过Ruby版本升级、运行环境基础镜像替换、OpenSSL依赖更新,刚好把默认校验配置从旧版本的“不校验”切换为新版本的“强制校验”,就会突然出现该报错。 - 服务端证书链变更
如果你的客户端版本本身已经默认开启证书校验,那报错大概率来自第三方API侧的证书调整:比如对方更换了SSL证书的签发CA、调整了证书链返回顺序、漏配了中间证书,而你本地系统/OpenSSL默认信任的CA证书库中没有对应的根证书,就会导致证书链验证失败,抛出相同错误。
补充建议
手动指定ca_file的方案可以解决当前问题,但更通用的维护方式是定期更新运行环境系统的CA证书库(比如更新系统的ca-certificates软件包),不需要在每个请求中单独指定证书路径,也能减少后续CA变更、证书过期带来的重复问题。
注意:不要为了快速修复将verify_mode设置为VERIFY_NONE,该配置会完全关闭SSL证书校验,存在被中间人攻击的安全风险。
内容的提问来源于stack exchange,提问作者John M
相关产品推荐
相关产品推荐

