问题
I'm issuing a HTTPS GET request to a REST service I own with httplib2 but we're getting the error:
[Errno 8] _ssl.c:504: EOF occurred in violation of protocol
All other clients works well (browser, Java client, etc...) with the minor exception that PHP curl needed to be set to use SSL v3.
I've searched around and it seems that it is indeed an error regarding SSL version, but I can't seem to find a way to change it in httplib2. Is there any way around it besides changing the following line in the source code:
# We should be specifying SSL version 3 or TLS v1, but the ssl module
# doesn't expose the necessary knobs. So we need to go with the default
# of SSLv23.
return ssl.wrap_socket(sock, keyfile=key_file, certfile=cert_file,
cert_reqs=cert_reqs, ca_certs=ca_certs)
回答1:
I developed this workaround for httplib2 :
import httplib2
# Start of the workaround for SSL3
# This is a monkey patch / module function overriding
# to allow pages that only work with SSL3
# Build the appropriate socket wrapper for ssl
try:
import ssl # python 2.6
httplib2.ssl_SSLError = ssl.SSLError
def _ssl_wrap_socket(sock, key_file, cert_file,
disable_validation, ca_certs):
if disable_validation:
cert_reqs = ssl.CERT_NONE
else:
cert_reqs = ssl.CERT_REQUIRED
# Our fix for sites the only accepts SSL3
try:
# Trying SSLv3 first
tempsock = ssl.wrap_socket(sock, keyfile=key_file, certfile=cert_file,
cert_reqs=cert_reqs, ca_certs=ca_certs,
ssl_version=ssl.PROTOCOL_SSLv3)
except ssl.SSLError, e:
tempsock = ssl.wrap_socket(sock, keyfile=key_file, certfile=cert_file,
cert_reqs=cert_reqs, ca_certs=ca_certs,
ssl_version=ssl.PROTOCOL_SSLv23)
return tempsock
httplib2._ssl_wrap_socket = _ssl_wrap_socket
except (AttributeError, ImportError):
httplib2.ssl_SSLError = None
def _ssl_wrap_socket(sock, key_file, cert_file,
disable_validation, ca_certs):
if not disable_validation:
raise httplib2.CertificateValidationUnsupported(
"SSL certificate validation is not supported without "
"the ssl module installed. To avoid this error, install "
"the ssl module, or explicity disable validation.")
ssl_sock = socket.ssl(sock, key_file, cert_file)
return httplib.FakeSocket(sock, ssl_sock)
httplib2._ssl_wrap_socket = _ssl_wrap_socket
# End of the workaround for SSL3
if __name__ == "__main__":
h1 = httplib2.Http()
resp, content = h1.request("YOUR_SSL3_ONLY_LINK_HERE", "GET")
print(content)
This workaround was based on the workarounds for urllib2 presented at this bug report http://bugs.python.org/issue11220,
Update: Presenting a solution for httplib2. I didn't notice you were using httplib2, I thought it was urllib2.
回答2:
Please refer to another StackOverflow threads that specify a solution. The way to specify a TLS version force the SSL version to TLSv1 as mentioned in the response by user favoretti within the provided link.
Hopefully, this works
来源:https://stackoverflow.com/questions/17916285/ssl-version-in-httplib2-eof-occurred-in-violation-of-protocol