我正在消费 Ebay Trading APIs使用 Ebay python sdk这是最终唱python-requests用于进行 API 调用。
一切正常,但最近几天我无法调用电话。我收到错误:
SSLError: bad handshake: Error([('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')],)
这是完整的回溯:
In [9]: response = api.execute('GetSessionID', data)
---------------------------------------------------------------------------
SSLError Traceback (most recent call last)
<ipython-input-9-eb33610c2a7f> in <module>()
----> 1 response = api.execute('GetSessionID', data)
/home/debian/.virtualenvs/myvirtualenv/local/lib/python2.7/site-packages/ebaysdk/connection.pyc in execute(self, verb, data, list_nodes, verb_attrs, files)
117
118 self.build_request(verb, data, verb_attrs, files)
--> 119 self.execute_request()
120
121 if hasattr(self.response, 'content'):
/home/debian/.virtualenvs/goplaces/local/lib/python2.7/site-packages/ebaysdk/connection.pyc in execute_request(self)
182 proxies=self.proxies,
183 timeout=self.timeout,
--> 184 allow_redirects=True
185 )
186
/home/debian/.virtualenvs/myvirtualenv/local/lib/python2.7/site-packages/requests/sessions.pyc in send(self, request, **kwargs)
574
575 # Send the request
--> 576 r = adapter.send(request, **kwargs)
577
578 # Total elapsed time of the request (approximately)
/home/debian/.virtualenvs/myvirtualenv/local/lib/python2.7/site-packages/requests/adapters.pyc in send(self, request, stream, timeout, verify, cert, proxies)
431 except (_SSLError, _HTTPError) as e:
432 if isinstance(e, _SSLError):
--> 433 raise SSLError(e, request=request)
434 elif isinstance(e, ReadTimeoutError):
435 raise ReadTimeout(e, request=request)
SSLError: bad handshake: Error([('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')],)
StackOverflow 上有很多相关问题,都是这样说的:
- 传递参数 verify=False
- 通过CA证书
- 在 cacert.pem file 中附加您的 CA 证书(我试过了,没用)
我不能这样做是因为:
- requests 被我的虚拟环境中的第三方库调用。
- 从安全角度来看这很糟糕。
此外,
- 我能够使用请求在同一 virtualenv 中进行其他 TSL 调用(例如 Amazon marketplace api),这不会导致错误的握手或任何其他 SSL 错误。
- Ebay SDK 在我的本地系统 (Mac OsX) 上运行良好,问题仅出现在我的生产服务器 (Google Cloud/Debian)
- chrome 在我的域上没有报告 SSL 错误
我不知道为什么会这样。
当我禁用 SSL3 时,为什么 SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed'
在回溯中。 (我对 SSL 了解不深)。
谢谢!
编辑:
# openssl version
OpenSSL 1.0.2e 3 Dec 2015
根据@Steffen Ullrich 的建议从源代码构建,从 1.0.1 升级到 openssl 1.0.2。
$ pip freeze | grep -i ssl
backports.ssl-match-hostname==3.4.0.2
pyOpenSSL==0.15.1
最佳答案
我猜这与 Python Urllib2 SSL error 有关,即 OpenSSL 底层实现中的多信任路径问题。有关问题的详细信息,请参阅此处。
要在不更改受信任的 CA 的情况下解决此问题,您需要有一个固定的 OpenSSL,即 OpenSSL 1.0.2。或者,您可以将一些旧的 CA 证书添加回您的信任库。
- pass argument verify=False
- pass CA certificate
- append you CA certificate in cacert.pem file (I tried this, didn't work)
... This is bad in security point of view.
虽然 verify=False
不利于安全,因为它禁用验证,但其他选项还不错,因为它们只添加额外的信任 anchor ,但保持启用验证。
Why SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed' is in traceback, when I have disabled SSL3.
即使它在那里谈论 SSLv3 也不是这个意思。 TLS 和 SSLv3 共享很多功能,即 TLS 1.0 实际上是 SSL 3.1。因此,OpenSSL 代码中的许多 SSL3_*
函数也与 TLS 1.x 一起使用,这会导致这些恼人的消息。
关于python - SSLError : bad handshake, Python 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34085552/