python ssl错误违反协议 - python

我正在尝试使用python使用以下代码登录并下载一些文件:

import sys
import urllib
import urllib2
import httplib, ssl, socket
class HTTPSConnectionV3(httplib.HTTPSConnection):
    def __init__(self, *args, **kwargs):
        httplib.HTTPSConnection.__init__(self, *args, **kwargs)

    def connect(self):
        sock = socket.create_connection((self.host, self.port), self.timeout)
        if self._tunnel_host:
            self.sock = sock
            self._tunnel()
        try:
            self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv3)
        except ssl.SSLError, e:
            print("Trying SSLv3.")
            #self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_TLSv1)
            self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv23)

class HTTPSHandlerV3(urllib2.HTTPSHandler):
    def https_open(self, req):
        return self.do_open(HTTPSConnectionV3, req)
# install opener
urllib2.install_opener(urllib2.build_opener(HTTPSHandlerV3()))
if __name__ == "__main__":
    ##fill the login form
    query={}
    query['username']='USER'
    query['password']='007'
    query['submit']='Submit'
    if len(sys.argv) != 2:
                    print >> sys.stderr, "missing date"
                    sys.exit()
    #submit the form
    #http_req = urllib2.Request(url='https://www.connect2nse.com/iislNet', data=urllib.urlencode(query))
    http_req = urllib2.Request(url='https://www.connect2nse.com/iislNet/Login.jsp', data=urllib.urlencode(query))
    #http_req = urllib2.Request(url='https://www.connect2nse.com/iislNet/index.html', data=urllib.urlencode(query))
    webpage = urllib2.urlopen(http_req)
    webpage_headers = webpage.info()
    #extract the cookie
    cookie = webpage_headers['Set-Cookie'].split(';', 1)[0]
    print >> sys.stderr, "Set-Cookie:", cookie
    http_req = urllib2.Request(url='https://connect2nse.com/iislNet/MY.jsp', headers={'Cookie': cookie})
    webpage = urllib2.urlopen(http_req)

我收到以下错误

Trying SSLv3.
Traceback (most recent call last):
  File "MYSCRIPT.py", line 51, in <module>
    webpage = urllib2.urlopen(http_req)
  File "/usr/lib/python2.7/urllib2.py", line 126, in urlopen
    return _opener.open(url, data, timeout)
  File "/usr/lib/python2.7/urllib2.py", line 400, in open
    response = self._open(req, data)
  File "/usr/lib/python2.7/urllib2.py", line 418, in _open
    '_open', req)
  File "/usr/lib/python2.7/urllib2.py", line 378, in _call_chain
    result = func(*args)
  File "MYSCRIPT.py", line 27, in https_open
    return self.do_open(HTTPSConnectionV3, req)
  File "/usr/lib/python2.7/urllib2.py", line 1177, in do_open
    raise URLError(err)
urllib2.URLError: <urlopen error [Errno 8] _ssl.c:504: EOF occurred in violation of protocol>

尽管到上个月为止一切正常,但现在却出现上述错误

我已经尝试过This link,但无济于事。
在我使用的python中使用请求
r = request.get('https://www.connect2nse.com/iislNet/Login.jsp',auth =('USER','007'))
r.status_code
401
但是我不确定如何继续使用请求。
尝试@Antti Haapala的解决方案对我不起作用,请在2.7.3&6上尝试

try: 
# self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv23) 
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_TLSv1) 
except ssl.SSLError, e: 
print("Trying SSLv3.",e) 
# self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=5) 
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv23)

TLSv1和SSLv23都给出类似的错误。

error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure' and
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure'

@ J.F。 Sebastian,谢谢,但是我100%确信登录名和密码正确无误,因为在chrome中使用相同的登录名和密码即可。当我使用TLSv1_2时,出现以下错误

 python MYSCRIPT.py 090315
Trying SSLv3.
Traceback (most recent call last):
  File "MYSCRIPT.py", line 51, in <module>
    webpage = urllib2.urlopen(http_req)
  File "/usr/lib/python2.7/urllib2.py", line 126, in urlopen
    return _opener.open(url, data, timeout)
  File "/usr/lib/python2.7/urllib2.py", line 400, in open
    response = self._open(req, data)
  File "/usr/lib/python2.7/urllib2.py", line 418, in _open
    '_open', req)
  File "/usr/lib/python2.7/urllib2.py", line 378, in _call_chain
    result = func(*args)
  File "MYSCRIPT.py", line 27, in https_open
    return self.do_open(HTTPSConnectionV3, req)
  File "/usr/lib/python2.7/urllib2.py", line 1174, in do_open
    h.request(req.get_method(), req.get_selector(), req.data, headers)
  File "/usr/lib/python2.7/httplib.py", line 958, in request
    self._send_request(method, url, body, headers)
  File "/usr/lib/python2.7/httplib.py", line 992, in _send_request
    self.endheaders(body)
  File "/usr/lib/python2.7/httplib.py", line 954, in endheaders
    self._send_output(message_body)
  File "/usr/lib/python2.7/httplib.py", line 814, in _send_output
    self.send(msg)
  File "/usr/lib/python2.7/httplib.py", line 776, in send
    self.connect()
  File "MYSCRIPT.py", line 22, in connect
    self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_TLSv1_2)
AttributeError: 'module' object has no attribute 'PROTOCOL_TLSv1_2'

该站点发布了兼容浏览器设置的通知,此后脚本开始出现故障this link shows compatibility, you need to click on NEW SSL DOC

python大神给出的解决方案

您的代码强制连接始终使用SSL 3协议,在最近的千年中,TLSv1取代了SSL 3。

在Pythons <2.7.9(2.7.8)中,您应该选择ssl.PROTOCOL_SSLv23,它将支持OpenSSL库支持的最大TLS编号。特别是在当前的OpenSSL版本中,它表示支持SSLv3TLSv1TLSv1.1TLSv1.2。与标志所说的不同,最新版本的OpenSSL将不接受SSLv2。

这样我们得到:

def connect(self):
    sock = socket.create_connection((self.host, self.port), self.timeout)
    if self._tunnel_host:
        self.sock = sock
        self._tunnel()

    self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
                                ssl_version=ssl.PROTOCOL_SSLv23)

如果连接了requests,则可能要使用它。您的授权应作为表单值和POST request发送:

data = {}
data['username']='USER'
data['password']='007'
data['submit']='Submit'
r = requests.post("https://www.connect2nse.com/iislNet/Login.jsp", data=data)

ssl.PROTOCOL_TLSv1_2出现在Python 2.7.9和3.4中,但即使在该版本号之前,也可以使用某些反向移植。

但是,如果PROTOCOL_TLSv1_2不在ssl模块中,则这也意味着TLS 1.2仅在具有硬编码协议常量(5)的情况下不能在Python中使用-reason is quite obvious from the _ssl source code-整数仅对Python扩展有意义模块,用于选择实际的构造方法。

在Python 2.7.9中,将有一个SSLContext对象,可用于set flags on for SSL socket creation;在那里至少可以尝试使用monkey_patch作为将来的证明,但是对于没有TLSv1.2补丁的版本则不可能。

关于如何禁用SSL 2和3,TLSv1.0,TLSv1.1,TLSv1.2的2.7.9示例代码,强制使用假设的TLSv1.3(?):

ssl_sock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_SSLv23)
ssl_sock.context.options |= ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 \
   | ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_2