fin*_*ris 29 python ssl https cisco
我正在将REST API用于Cisco CMX设备,并尝试编写Python代码,该代码向API发出GET请求以获取信息.代码如下,除了更改必要的信息外,与文件中的代码相同.
from http.client import HTTPSConnection
from base64 import b64encode
# Create HTTPS connection
c = HTTPSConnection("0.0.0.0")
# encode as Base64
# decode to ascii (python3 stores as byte string, need to pass as ascii
value for auth)
username_password = b64encode(b"admin:password").decode("ascii")
headers = {'Authorization': 'Basic {0}'.format(username_password)}
# connect and ask for resource
c.request('GET', '/api/config/v1/aaa/users', headers=headers)
# response
res = c.getresponse()
data = res.read()
Run Code Online (Sandbox Code Playgroud)
但是,我不断收到以下错误:
Traceback (most recent call last):
File "/Users/finaris/PycharmProjects/test/test/test.py", line 14, in <module>
c.request('GET', '/api/config/v1/aaa/users', headers=headers)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1106, in request
self._send_request(method, url, body, headers)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1151, in _send_request
self.endheaders(body)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1102, in endheaders
self._send_output(message_body)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 934, in _send_output
self.send(msg)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 877, in send
self.connect()
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1260, in connect
server_hostname=server_hostname)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 377, in wrap_socket
_context=self)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 752, in __init__
self.do_handshake()
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 988, in do_handshake
self._sslobj.do_handshake()
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 633, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:645)
Run Code Online (Sandbox Code Playgroud)
我也尝试更新OpenSSL,但没有效果.
J0A*_*NMM 53
我有同样的错误,谷歌把我带到这个问题,所以这就是我所做的,希望它能帮助处于类似情况的其他人.
这适用于OS X.
检查终端我有哪个版本的OpenSSL:
$ python3 -c "import ssl; print(ssl.OPENSSL_VERSION)"
>> OpenSSL 0.9.8zh 14 Jan 2016
Run Code Online (Sandbox Code Playgroud)
由于我的OpenSSL版本太旧,所接受的答案无效.
所以我不得不更新OpenSSL.要做到这一点,我更新的Python到最新版本(从3.5版到3.6版)与自制,以下一些建议的步骤在这里:
$ brew update
$ brew install openssl
$ brew install python3
Run Code Online (Sandbox Code Playgroud)
然后我遇到了PATH和使用的python版本的问题,所以我创建了一个新的virtualenv
确保最新版本的python被采用:
$ virtualenv webapp --python=python3.6
Run Code Online (Sandbox Code Playgroud)
问题解决了.
Jam*_*Lim 28
你唯一要做的就是安装requests[security]
在你的virtualenv中.您不应该使用Python 3(它应该在Python 2.7中工作).此外,如果您使用的是最新版本的macOS,则不必使用homebrew
单独安装OpenSSL.
$ virtualenv --python=/usr/bin/python tempenv # uses system python
$ . tempenv/bin/activate
$ pip install requests
$ python
>>> import ssl
>>> ssl.OPENSSL_VERSION
'OpenSSL 0.9.8zh 14 Jan 2016' # this is the built-in openssl
>>> import requests
>>> requests.get('https://api.github.com/users/octocat/orgs')
requests.exceptions.SSLError: HTTPSConnectionPool(host='api.github.com', port=443): Max retries exceeded with url: /users/octocat/orgs (Caused by SSLError(SSLError(1, u'[SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:590)'),))
$ pip install 'requests[security]'
$ python # install requests[security] and try again
>>> import requests
>>> requests.get('https://api.github.com/users/octocat/orgs')
<Response [200]>
Run Code Online (Sandbox Code Playgroud)
requests[security]
允许请求在协商连接时使用最新版本的TLS.macOS上的内置openssl支持TLS v1.2.
在安装自己的OpenSSL版本之前,请先问一下这个问题:Google Chrome如何加载https://github.com?
没有一个接受的答案指出我正确的方向,这仍然是搜索主题时出现的问题,所以这是我(部分)成功的传奇.
背景:我在Beaglebone Black上运行Python脚本,使用python-poloniex库轮询加密货币交换Poloniex .它突然停止使用TLSV1_ALERT_PROTOCOL_VERSION错误.
事实证明,OpenSSL很好,并试图强制v1.2连接是一个巨大的疯狂追逐 - 图书馆将根据需要使用最新版本.链中的弱链接实际上是Python,它只定义了ssl.PROTOCOL_TLSv1_2
,因此从版本3.4开始支持TLS v1.2.
与此同时,Beaglebone上的Debian版本认为Python 3.3是最新版本.我使用的解决方法是从源代码安装Python 3.5(3.4可能最终也可以工作,但经过几个小时的试验和错误我已经完成):
sudo apt-get install build-essential checkinstall
sudo apt-get install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev
wget https://www.python.org/ftp/python/3.5.4/Python-3.5.4.tgz
sudo tar xzf Python-3.5.4.tgz
cd Python-3.5.4
./configure
sudo make altinstall
Run Code Online (Sandbox Code Playgroud)
也许并非所有这些包都是必需的,但是一次安装它们可以节省大量的重试次数.在altinstall
防止重挫现有的Python二进制文件,安装的安装python3.5
,而不是,虽然这并不意味着你必须重新安装附加库.在./configure
花了好五到十分钟.在make
花了几个小时.
现在,直到我终于跑了,这仍然没有用
sudo -H pip3.5 install requests[security]
Run Code Online (Sandbox Code Playgroud)
哪个也安装pyOpenSSL
,cryptography
和idna
.我怀疑pyOpenSSL
是关键,所以也许pip3.5 install -U pyopenssl
已经足够了,但我已经花了很长时间才确定这一点.
总而言之,如果在Python中出现TLSV1_ALERT_PROTOCOL_VERSION错误,可能是因为您无法支持TLS v1.2.要添加支持,您至少需要以下内容:
这让我超过了TLSV1_ALERT_PROTOCOL_VERSION,现在我开始与SSL23_GET_SERVER_HELLO战斗了.
事实证明这是回到Python选择错误的SSL版本的原始问题.这可以通过使用此技巧来安装请求会话来确认ssl_version=ssl.PROTOCOL_TLSv1_2
.没有它,使用SSLv23并出现SSL23_GET_SERVER_HELLO错误.有了它,请求成功.
最后的战斗是在第三方库中深入请求时强制选择TLSv1_2.无论这种方法和这种方法应该做的伎俩,但没有取得任何区别.我的最终解决方案是可怕的,但有效.我编辑/usr/local/lib/python3.5/site-packages/urllib3/util/ssl_.py
并改变了
def resolve_ssl_version(candidate):
"""
like resolve_cert_reqs
"""
if candidate is None:
return PROTOCOL_SSLv23
if isinstance(candidate, str):
res = getattr(ssl, candidate, None)
if res is None:
res = getattr(ssl, 'PROTOCOL_' + candidate)
return res
return candidate
Run Code Online (Sandbox Code Playgroud)
至
def resolve_ssl_version(candidate):
"""
like resolve_cert_reqs
"""
if candidate is None:
return ssl.PROTOCOL_TLSv1_2
if isinstance(candidate, str):
res = getattr(ssl, candidate, None)
if res is None:
res = getattr(ssl, 'PROTOCOL_' + candidate)
return res
return candidate
Run Code Online (Sandbox Code Playgroud)
瞧,我的脚本最终可以再次联系服务器.
我相信TLSV1_ALERT_PROTOCOL_VERSION
提示您服务器不想与您交谈TLS v1.0.尝试仅通过坚持这些行来指定TLS v1.2:
import ssl
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
# Create HTTPS connection
c = HTTPSConnection("0.0.0.0", context=context)
Run Code Online (Sandbox Code Playgroud)
注意,您可能需要足够新版本的Python(可能是2.7.9+?)和可能的OpenSSL(我有"OpenSSL 1.0.2k 2017年1月26日",以上似乎有效,YMMV)
对于 Mac OS X
1) 使用从 Python 语言官方网站https://www.python.org/downloads/下载的本机应用程序安装程序更新到 Python 3.6.5
我发现安装程序负责更新新 Python 的链接和符号链接比自制软件要好得多。
2) 使用“./Install Certificates.command”安装新证书,它位于刷新后的 Python 3.6 目录中
> cd "/Applications/Python 3.6/"
> sudo "./Install Certificates.command"
Run Code Online (Sandbox Code Playgroud)
从2018年7月开始,Pypi现在要求连接到它的客户端使用TLS 1.2。如果您使用的是MacOS(2.7.10)附带的python版本,则这是一个问题,因为它仅支持TLS 1.0。您可以更改python用于解决问题的ssl版本,也可以升级到新版本的python。使用homebrew在默认库位置之外安装新版本的python。
brew install python@2
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
82141 次 |
最近记录: |