请求模块抛出 OpenSSL.SSL.Error [英] Requests module throwing OpenSSL.SSL.Error
问题描述
我正在使用来自 euronext.com 的 REST API,为了更进一步,我需要验证服务器证书并通过模块请求发送我自己的客户端证书.
I'm using a REST API from euronext.com, to go any further I need to verify the server certificate and send my own client certificate through the module requests.
我已经用 curl 做了一些测试,.crt/.pem 文件都被接受了.
I already did some testing with curl, both .crt/.pem files were accepted.
但是请求仍在抛出:
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): saturn-api-h.euronext.com
Traceback (most recent call last):
File "C:\python36\lib\site-packages\urllib3\contrib\pyopenssl.py", line 441, in wrap_socket
cnx.do_handshake()
File "C:\python36\lib\site-packages\OpenSSL\SSL.py", line 1806, in do_handshake
self._raise_ssl_error(self._ssl, result)
File "C:\python36\lib\site-packages\OpenSSL\SSL.py", line 1546, in _raise_ssl_error
_raise_current_error()
File "C:\python36\lib\site-packages\OpenSSL\_util.py", line 54, in exception_from_error_queue
raise exception_type(errors)
OpenSSL.SSL.Error: [('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')]
我为解决问题所做的尝试:
What I did try to solve the issue :
- 遵循请求文档
- 将请求模块更新到 2.18.4
- 安装 pyOpenSSL 17.5.0
- 检查 .crt/.pem 格式
- 卷曲测试
工作卷曲:
curl -i -vvv -X POST https://saturn-api-h.euronext.com/SaturnWebServices/rest/Authentication/AuthenticateUser -H "Content-Type: application/json" --cert ./client.crt --cacert ./digicert-full-chain.crt
如果有一个有效的 Authorization 标头,它会返回一个 200 状态码,没有它会返回 401拒绝访问!".如果证书验证失败,它会重定向到 euronext.com,状态码为 302.
With a valid Authorization headers it return a 200 status code, without it 401 "Access denied!". If the certificate validation fails, it redirects to euronext.com with status code 302.
有问题的蟒蛇:
endpoint = 'https://saturn-api-h.euronext.com/SaturnWebServices/rest/Authentication/AuthenticateUser'
headers = { 'Content-Type': 'application/json', } #'Authorization': 'Basic <auth_string>',
r = requests.post(endpoint, headers = headers, verify = './digicert-full-chain.crt', cert = './client.crt')
证书:
digicert-full-chain.crt 包含来自 DigiCert 的完整链:
digicert-full-chain.crt is containing the full chain from DigiCert:
- DigiCertAssuredIDRootCA.pem
- DigiCertSHA2AssuredIDCA.pem
- DigiCertSHA2SecureServerCA.pem
client.crt 包含我们的证书及其密钥.
client.crt is containg our certificate and its key.
为什么 curl 命令有效,而 python 的 requests 模块却失败了?
Why is curl command working whereas python's requests module is failling?
有没有办法从请求模块中显示完整的握手过程?
Is there any way to show the complete handshake process from the requests module?
推荐答案
我自己解决了这个问题,整个链中缺少一个证书.
I solved the problem myself, a certificate was missing from the full chain.
做/usr/local/lib/python3.4/dist-packages/certifi/cacert.pem >certifi-digicert.pem;digicert-full-chain.pem >>certifi-digicert.pem
并将生成的证书传递给 verify 参数起作用.
Doing /usr/local/lib/python3.4/dist-packages/certifi/cacert.pem > certifi-digicert.pem; digicert-full-chain.pem >> certifi-digicert.pem
and passing the resulting certificate to the verify argument worked.
作为旁注,我使用了 strace 命令来比较 python 和 curl 的证书位置:
As a side note, I used the strace command to compare certificate locations from both python and curl:
strace
|&grep 打开 |grep -E 'crt|pem' strace
|&grep 打开 |grep -E 'crt|pem'
我还检查了 Wireshark 以获得完整的握手过程,pyOpenSSL 模块在服务器的证书请求后收到错误.警报(级别:致命,描述:未知 CA)
.
I also checked with Wireshark to get the full handshake process, the pyOpenSSL module was getting an error after the server's Certificate Request. Alert (Level: Fatal, Description: Unknown CA)
.
这篇关于请求模块抛出 OpenSSL.SSL.Error的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!