我正在使用 euronext.com 的 REST API,要更进一步,我需要验证服务器证书并通过模块请求发送我自己的客户端证书。
我已经用curl做了一些测试,两个.crt/.pem文件都被接受了。
但是请求仍然抛出:
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): saturn-api-h.euronext.com
Traceback (most recent call last):
File "C:python36libsite-packagesurllib3contribpyopenssl.py", line 441, in wrap_socket
cnx.do_handshake()
File "C:python36libsite-packagesOpenSSLSSL.py", line 1806, in do_handshake
self._raise_ssl_error(self._ssl, result)
File "C:python36libsite-packagesOpenSSLSSL.py", line 1546, in _raise_ssl_error
_raise_current_error()
File "C:python36libsite-packagesOpenSSL_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')]
我所做的尝试是解决问题的:
- 遵循请求文档
- 将请求模块更新到 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
使用有效的授权标头,它返回 200 状态代码,而不返回 401"访问被拒绝!如果证书验证失败,它将重定向到状态代码为 302 的 euronext.com。
有问题的蟒蛇:
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 的完整链:
- DigiCertAssuredIDRootCA.pem
- DigiCertSHA2AssuredIDCA.pem
- DigiCertSHA2SecureServerCA.pem
client.crt包含我们的证书及其密钥。
为什么 curl 命令工作,而 python 的请求模块失败?
有没有办法从请求模块显示完整的握手过程?
我自己解决了这个问题,整个链中缺少证书。
执行/usr/local/lib/python3.4/dist-packages/certifi/cacert.pem > certifi-digicert.pem; digicert-full-chain.pem >> certifi-digicert.pem
并将生成的证书传递给验证参数是有效的。
作为旁注,我使用 strace 命令来比较来自 python 和 curl 的证书位置:
strace <python_command> |& grep open | grep -E 'crt|pem'
strace <curl_command> |& grep open | grep -E 'crt|pem'
我还与Wireshark进行了检查以获取完整的握手过程,pyOpenSSL模块在服务器的证书请求后出现错误。Alert (Level: Fatal, Description: Unknown CA)
.