我正在尝试使用python中的请求库向服务器发送POST调用。之前我能够成功发送POST调用,但最近,服务器弃用了TLSv1.0,现在只支持TLSv1.1和TLSv1.2。现在相同的代码抛出了一个" requests.exceptions.SSLError:EOF违反协议(_ssl.c:590)"错误。
我在stackoverflow Python Requests requests.exceptions.SSLError: [Errno 8] _ssl.c:504: EOF occurred in violation of protocol上发现了这个线程,它说我们需要子类化HTTPAdapter,之后会话对象将使用TLSv1。我相应地更改了我的代码,这是我的新代码
class MyAdapter(HTTPAdapter):
def init_poolmanager(self, connections, maxsize, block=False):
self.poolmanager = PoolManager(num_pools=connections,
maxsize=maxsize,
block=block,
ssl_version=ssl.PROTOCOL_TLSv1)
url="https://mywebsite.com/ui/"
headers={"Cookie":"some_value","X-CSRF-Token":"some value","Content-Type":"application/json"}
payload={"name":"some value","Id":"some value"}
s = requests.Session()
s.mount('https://', MyAdapter())
r=s.post(url,json=payload,headers=headers)
html=r.text
print html
但即使使用了这个,我也会得到同样的错误" EOF违反了协议(_ssl.c:590)"。
我的第一个问题是,我在某处读取默认使用ssl的请求。我知道我的服务器使用的是TLSv1.0,我的代码是否正常工作,因为TLSv1.0与ssl3.0向后兼容?
我的第二个问题是,我上面提到的stackoverflow线程使用了我将我的代码更改为子类HTTPAdapter,表示这将适用于TLSv1。但是由于我的服务器中不推荐使用TLSv1.0,这段代码是否仍然有效?
答案 0 :(得分:6)
TLS堆栈将使用自动提供的最佳版本。如果在服务器上禁用TLS 1.0支持时它不再起作用,则通常意味着本地TLS堆栈不支持更新的协议版本,如TLS 1.2。在Mac OS X上经常出现这种情况,因为它附带了旧版本的OpenSSL(0.9.8)。在这种情况下,没有python代码可以帮助您解决问题,但您需要获得一个使用较新版本的OpenSSL的python。
要检查您正在使用哪个openssl版本,请在python中执行以下命令:
import ssl
print ssl.OPENSSL_VERSION
要获得对TLS 1.2的支持,您需要OpenSSL版本1.0.2或1.0.1。如果您只有1.0.0或0.9.8,则需要升级python + OpenSSL。有关如何执行此操作的详细信息,请参阅Updating openssl in python 2.7。
答案 1 :(得分:1)
我从非常老的服务器(由https://www.ssllabs.com评为F)获得随机连接错误,直到我没有开始在HTTPAdapter中使用此代码:
def init_poolmanager(self, *args, **kwargs):
ssl_context = ssl.create_default_context()
# Sets up old and insecure TLSv1.
ssl_context.options &= ~ssl.OP_NO_TLSv1_3 & ~ssl.OP_NO_TLSv1_2 & ~ssl.OP_NO_TLSv1_1
ssl_context.minimum_version = ssl.TLSVersion.TLSv1
# Also you could try to set ciphers manually as it was in my case.
# On other ciphers their server was reset the connection with:
# [Errno 104] Connection reset by peer
# ssl_context.set_ciphers("ECDHE-RSA-AES256-SHA")
# See urllib3.poolmanager.SSL_KEYWORDS for all available keys.
kwargs["ssl_context"] = ssl_context
return super().init_poolmanager(*args, **kwargs)