使用Python requests+certifi调用HTTPS接口遇SSL证书验证失败求助
问题描述
我尝试使用Python的requests库和certifi库发起HTTPS请求,代码如下:
import certifi import requests # 注:原代码遗漏此导入,实际运行需补充 url = 'https://10.0.0.39:4455/api/cars' response = requests.get(url, verify=certifi.where()) if response.status_code == 200: print(response.json()) else: print(f'Request failed with status code {response.status_code}: {response.text}')
但持续收到如下错误信息:
requests.exceptions.SSLError: HTTPSConnectionPool(host='https://10.0.0.39/api/cars', port=4455): Max retries exceeded with url: /api/cars (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:852)'),))
我已通过pip安装并导入certifi模块用于验证SSL/TLS证书,但仍出现该错误。请求的Flask API运行在另一台电脑(IP为10.0.0.39)上且已启用SSL证书,请问该如何解决此问题?
解决方案
1. 直接指定API端的证书文件
certifi仅包含公共根CA证书,若Flask API使用的是自签名证书或内部CA签发的证书,certifi的证书池不会收录这类证书,导致验证失败。解决方法:
- 将Flask端使用的证书文件(如
server.crt)复制到请求端,在请求时指定该证书路径:response = requests.get(url, verify="/本地路径/server.crt") - 若为内部CA签发的证书,可直接指定CA证书路径:
response = requests.get(url, verify="/本地路径/ca_root.crt")
2. 修复证书主机名不匹配问题
SSL证书的Subject Alternative Name (SAN)或Common Name (CN)必须与请求的主机名(此处为10.0.0.39)一致。若证书是用域名生成的,用IP访问会触发验证失败:
- 重新生成包含
10.0.0.39作为SAN/CN的证书,替换Flask端的证书文件; - 或在本地
hosts文件添加映射(如10.0.0.39 my-api.local),改用域名https://my-api.local:4455/api/cars发起请求,确保证书的SAN/CN包含该域名。
3. 临时关闭验证(仅测试环境)
若为调试测试场景,可临时关闭SSL验证,生产环境绝对禁止使用:
response = requests.get(url, verify=False)
4. 检查certifi路径与完整性
先确认certifi的证书路径是否正确,文件是否完整:
import certifi print(certifi.where())
若路径异常或文件损坏,重新安装certifi:
pip uninstall certifi -y pip install certifi
5. 验证Flask端SSL配置正确性
确保Flask API正确加载证书与密钥文件,启动代码示例:
from flask import Flask app = Flask(__name__) @app.route('/api/cars') def get_cars(): return {"cars": ["Toyota", "Honda"]} if __name__ == '__main__': # 确保证书和密钥路径正确 app.run(host='0.0.0.0', port=4455, ssl_context=('server.crt', 'server.key'))
若Flask端证书/密钥路径错误,也会导致客户端验证失败。
内容的提问来源于stack exchange,提问作者gapanihu
相关产品推荐
相关产品推荐

