Python请求requests.exceptions.SSLError: _ssl.c:504:EOF违反协议
我在Ubuntu 12.10与OpenSSL 1.0.1c,Python 2.7.3, 请求 1.0.3和1.0.4(尝试两个),并试图连接到urlvariables与下面的代码。
def SendInitialRequest(xmlmessage, redirecturl): url = 'https://centineltest.cardinalcommerce.com/maps/txns.asp' payload = 'cmpi_msg=' + ET.tostring(xmlmessage) headers = { 'Content-Type': 'application/x-www-form-urlencoded', } r = requests.post(url, data=payload, headers=headers, verify=None) print r.text
它会抛出以下错误:
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "clams/libs/centinel/thinclient.py", line 134, in SendInitialRequest r = requests.post(url, data=payload, headers=headers, verify=None) File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/api.py", line 87, in post return request('post', url, data=data, **kwargs) File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/api.py", line 44, in request return session.request(method=method, url=url, **kwargs) File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/sessions.py", line 269, in request resp = self.send(prep, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies) File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/sessions.py", line 364, in send r = adapter.send(request, **kwargs) File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/adapters.py", line 163, in send raise SSLError(e) requests.exceptions.SSLError: [Errno 8] _ssl.c:504: EOF occurred in violation of protocol
尝试与openssl的连接返回以下内容:
$ openssl s_client -connect centineltest.cardinalcommerce.com:443 CONNECTED(00000003) 140019346777760:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:177: --- no peer certificate available --- No client certificate CA names sent --- SSL handshake has read 0 bytes and written 226 bytes --- New, (NONE), Cipher is (NONE) Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE ---
如果我强制它使用tls1它工作(输出截断):
$ openssl s_client -tls1 -connect centineltest.cardinalcommerce.com:443 CONNECTED(00000003) depth=2 C = US, O = "thawte, Inc.", OU = Certification Services Division, OU verify error:num=20:unable to get local issuer certificate verify return:0 ---
我已经看到了许多错误报告 。 但是,我还没有find一种方法来解决它使用python请求库。 任何援助将不胜感激。
在请求问题页面上为此转发此信息:
请求“不支持在版本1之前执行此操作。在版本1之后,您需要inheritanceHTTPAdapter,如下所示:
from requests.adapters import HTTPAdapter from requests.packages.urllib3.poolmanager import PoolManager import ssl 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)
当你这样做的时候,你可以这样做:
import requests s = requests.Session() s.mount('https://', MyAdapter())
然后通过该会话对象的任何请求将使用TLSv1。
设置verify = False只跳过validation服务器证书,但不会帮助解决SSL协议错误。
这个问题很可能是由于Web服务器上禁用了SSLv2,但Python 2.x默认情况下会尝试与PROTOCOL_SSLv23build立连接。 这发生在https://github.com/python/cpython/blob/360aa60b2a36f5f6e9e20325efd8d472f7559b1e/Lib/ssl.py#L1057
您可以通过覆盖ssl_version关键字参数来将ssl.wrap_socket()修补到ssl模块中。 以下代码可以按原样使用。 在提出任何请求之前,请在程序开始时进行此操作。
import ssl from functools import wraps def sslwrap(func): @wraps(func) def bar(*args, **kw): kw['ssl_version'] = ssl.PROTOCOL_TLSv1 return func(*args, **kw) return bar ssl.wrap_socket = sslwrap(ssl.wrap_socket)
为我解决的requests
安装“安全”包extras:
sudo apt-get install libffi-dev
sudo pip安装-U请求[安全]
这是一个已知的bug,你可以用黑客来解决它:
打开site-packages/requests/packages/urllib3/connectionpool.py
(或者在你自己的项目中创build一个请求的本地副本),然后修改下面的代码块:
def connect(self): # Add certificate verification sock = socket.create_connection((self.host, self.port), self.timeout) # Wrap socket using verification with the root certs in # trusted_root_certs self.sock = ssl_wrap_socket(sock, self.key_file, self.cert_file, cert_reqs=self.cert_reqs, ca_certs=self.ca_certs, server_hostname=self.host, ssl_version=self.ssl_version)
至:
def connect(self): # Add certificate verification sock = socket.create_connection((self.host, self.port), self.timeout) # Wrap socket using verification with the root certs in # trusted_root_certs self.sock = ssl_wrap_socket(sock, self.key_file, self.cert_file, cert_reqs=self.cert_reqs, ca_certs=self.ca_certs, server_hostname=self.host, ssl_version=ssl.PROTOCOL_TLSv1)
否则,我想有一个重写的地方是不那么hacky,但我找不到一个几眼。
注意 :在旁注中,来自PIP(1.0.4)的MacOS requests
仅适用于您提供的URL。
我遇到了这个错误,并且修复似乎closures了Python 2.7不支持的SNI:
http://bugs.python.org/issue5639
urllib3在Google App Engine上的python 2.7 SNI错误
对于无法得到上面的人修复工作。
不得不改变文件ssl.py来解决它。 查找函数create_default_context并更改行:
context = SSLContext(PROTOCOL_SSLv23)
至
context = SSLContext(PROTOCOL_TLSv1)
也许有人可以创build更简单的解决scheme,而不编辑ssl.py?
我遇到过同样的问题:
引发SSLError(e)
requests.exceptions.SSLError:[Errno 8] _ssl.c:504:EOF违反协议
我有小提琴手跑,我停止了提琴手捕获,并没有看到这个错误。 可能是因为小提琴手。
不幸的是接受的答案不适合我。 作为一个临时解决方法,您也可以在连接到安全网站时使用verify=False
。
从Python请求抛出SSLError
requests.get('https://example.com', verify=True)
通过TLS连接到RabbitMQ MQTT服务器时,出现此错误。 我很确定服务器坏了,但无论如何,它与OpenSSL 1.0.1,但不是 OpenSSL 1.0.2。
你可以用Python来检查你的版本:
import ssl ssl.OPENSSL_VERSION
我不确定如何降级Python中的OpenSSL(至less在Windows上至less是静态链接的),而不是使用旧版本的Python。
我有类似的问题,我认为如果我们简单地忽略ssl
validation将像魅力一样工作,为我工作。 所以用https
scheme连接到服务器,但指示他们不要validation证书。
使用requests
。 只要提到verify=False
而不是None
requests.post(url, data=payload, headers=headers, verify=False)
希望这将为需要:)的人工作。