Python Requests请求SSL证书验证失败问题求助
解决CentOS 8上Python requests的SSL证书验证失败问题
问题情况
本地Windows 10机器上运行的Python脚本,通过requests库调用内部API完全正常,但部署到RHEL CentOS 8服务器时,出现SSL证书验证失败错误:
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)
要求必须保持SSL验证,不能使用verify=False的不安全方式。
已知信息
- 使用Python的requests库发起请求
- 自行创建了用于验证的.pem文件,格式为多份证书拼接:
-----BEGIN CERTIFICATE----- ********************************** -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- ********************************** -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- ********************************** -----END CERTIFICATE----- - 脚本在两台机器上完全一致
- 服务器可向其他系统发起正常的SSL验证请求
- 目标API使用的加密套件在
openssl ciphers输出列表中存在 - 请求代码:
response = requests.get(team_search, auth=(api_id, api_key), headers=headers, verify=certificate)
完整错误回溯
Traceback (most recent call last): File "/path/.local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 703, in urlopen httplib_response = self._make_request( File "/path/.local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 386, in _make_request self._validate_conn(conn) File "/path/.local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 1042, in _validate_conn conn.connect() File "/path/.local/lib/python3.9/site-packages/urllib3/connection.py", line 414, in connect self.sock = ssl_wrap_socket( File "/path/.local/lib/python3.9/site-packages/urllib3/util/ssl_.py", line 449, in ssl_wrap_socket ssl_sock = _ssl_wrap_socket_impl( File "/path/.local/lib/python3.9/site-packages/urllib3/util/ssl_.py", line 493, in _ssl_wrap_socket_impl return ssl_context.wrap_socket(sock, server_hostname=server_hostname) File "/usr/lib64/python3.9/ssl.py", line 500, in wrap_socket return self.sslsocket_class._create( File "/usr/lib64/python3.9/ssl.py", line 1040, in _create self.do_handshake() File "/usr/lib64/python3.9/ssl.py", line 1309, in do_handshake self._sslobj.do_handshake() ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/path/.local/lib/python3.9/site-packages/requests/adapters.py", line 489, in send resp = conn.urlopen( File "/path/.local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 787, in urlopen retries = retries.increment( File "/path/.local/lib/python3.9/site-packages/urllib3/util/retry.py", line 592, in increment raise MaxRetryError(_pool, url, error or ResponseError(cause)) urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='api.veracode.com', port=443): Max retries exceeded with url: /api/authn/v2/teams/?page=0&size=1000 (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)'))) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/path/WebApps/access-review-test/PAR/manage.py", line 21, in <module> main() File "/path/WebApps/access-review-test/PAR/manage.py", line 17, in main execute_from_command_line(sys.argv) File "/path/.local/lib/python3.9/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line utility.execute() File "/path/.local/lib/python3.9/site-packages/django/core/management/__init__.py", line 440, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/path/.local/lib/python3.9/site-packages/django/core/management/base.py", line 414, in run_from_argv self.execute(*args, **cmd_options) File "/path/.local/lib/python3.9/site-packages/django/core/management/base.py", line 460, in execute output = self.handle(*args, **options) File "/path/WebApps/access-review-test/PAR/AccessReview/management/commands/update_veracodeusers.py", line 41, in handle response = requests.get(team_search, auth=RequestsAuthPluginVeracodeHMAC(api_id, api_key), headers=headers, verify=certificate) File "/path/.local/lib/python3.9/site-packages/requests/api.py", line 73, in get return request("get", url, params=params, **kwargs) File "/path/.local/lib/python3.9/site-packages/requests/api.py", line 59, in request return session.request(method=method, url=url, **kwargs) File "/path/.local/lib/python3.9/site-packages/requests/sessions.py", line 587, in request resp = self.send(prep, **send_kwargs) File "/path/.local/lib/python3.9/site-packages/requests/sessions.py", line 701, in send r = adapter.send(request, **kwargs) File "/path/.local/lib/python3.9/site-packages/requests/adapters.py", line 563, in send raise SSLError(e, request=request) requests.exceptions.SSLError: HTTPSConnectionPool(host='api.veracode.com', port=443): Max retries exceeded with url: /api/authn/v2/teams/?page=0&size=1000 (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)')))
解决方案
1. 确保.pem包含完整的证书链
本地Windows可能自动补充缺失的根/中间证书,但CentOS不会。执行以下命令提取目标API的完整证书链:
openssl s_client -connect api.veracode.com:443 -showcerts
将输出中所有-----BEGIN CERTIFICATE-----到-----END CERTIFICATE-----的内容按顺序拼接,替换现有.pem文件,确保从服务器证书、中间证书到根证书的完整链条都包含。
2. 检查证书文件的权限和路径
- 确保脚本运行用户能读取.pem文件,设置权限:
chmod 644 /path/to/your/certificate.pem - 脚本中
verify参数使用绝对路径,避免相对路径导致服务器上找不到文件。
3. 合并系统默认CA证书与自定义证书
如果自定义.pem仅包含中间证书,可将系统默认的CA根证书合并进去:
cat /etc/pki/tls/certs/ca-bundle.crt /path/to/your/certificate.pem > /path/to/combined_certs.pem
然后修改脚本,将verify指向合并后的combined_certs.pem。
4. 配置Python的SSL验证环境
- 查看Python默认的证书路径:
python -c "import ssl; print(ssl.get_default_verify_paths())" - 若虚拟环境使用独立的CA存储,可设置环境变量让requests全局使用自定义证书:
或在脚本开头添加:export REQUESTS_CA_BUNDLE=/path/to/your/certificate.pemimport os os.environ['REQUESTS_CA_BUNDLE'] = '/path/to/your/certificate.pem'
内容的提问来源于stack exchange,提问作者Sogetsue
相关产品推荐
相关产品推荐

