2012-03-23 26 views
10

在这一天花了很长时间,我真的在我的束手无策。我有一台安装了Python 2.6.6/2.7.2的机器“A”,另一台安装了Python 2.6.7/2.7.2的机器“B”。Urllib.urlopen()适用于一台机器上的Python 2.6.6的SSLv3网址,但不适用于另一台机器上的2.6.7/2.7.2

在计算机A上,我可以使用Python 2.6.6而不是2.7.2获得使用urllib2.urlopen('https://fed.princeton.edu')的SSLv3加密网站。

在机器B上,我无法使用Python版本获取该网站。

通过拿不到,我的意思是我的错误:

Traceback: 
File "/usr/local/lib/python2.7/dist-packages/Django-1.3.1-py2.7.egg/django/core/handlers/base.py" in get_response 
    111.       response = callback(request, *callback_args, **callback_kwargs) 
File "/usr/local/lib/python2.7/dist-packages/django_cas-2.0.3-py2.7.egg/django_cas/views.py" in login 
    78.   user = auth.authenticate(ticket=ticket, service=service) 
File "/usr/local/lib/python2.7/dist-packages/Django-1.3.1-py2.7.egg/django/contrib/auth/__init__.py" in authenticate 
    55.    user = backend.authenticate(**credentials) 
File "/usr/local/lib/python2.7/dist-packages/django_cas-2.0.3-py2.7.egg/django_cas/backends.py" in authenticate 
    72.   username = _verify(ticket, service) 
File "/usr/local/lib/python2.7/dist-packages/django_cas-2.0.3-py2.7.egg/django_cas/backends.py" in _verify_cas2 
    46.  page = urlopen(url) 
File "/usr/lib/python2.7/urllib.py" in urlopen 
    84.   return opener.open(url) 
File "/usr/lib/python2.7/urllib.py" in open 
    205.     return getattr(self, name)(url) 
File "/usr/lib/python2.7/urllib.py" in open_https 
    435.    h.endheaders(data) 
File "/usr/lib/python2.7/httplib.py" in endheaders 
    954.   self._send_output(message_body) 
File "/usr/lib/python2.7/httplib.py" in _send_output 
    814.   self.send(msg) 
File "/usr/lib/python2.7/httplib.py" in send 
    776.     self.connect() 
File "/usr/lib/python2.7/httplib.py" in connect 
    1161.    self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file) 
File "/usr/lib/python2.7/ssl.py" in wrap_socket 
    372.      ciphers=ciphers) 
File "/usr/lib/python2.7/ssl.py" in __init__ 
    134.     self.do_handshake() 
File "/usr/lib/python2.7/ssl.py" in do_handshake 
    296.   self._sslobj.do_handshake() 

Exception Type: IOError at /login 
Exception Value: [Errno socket error] [Errno 1] _ssl.c:503: error:140773F2:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert unexpected message 

首先,我很困惑的东西,关于早期版本的Python工作不会在稍后机械作业。我也很困惑2.6.6上的某些工作在2.6.7上不起作用(尽管在不同的机器上)。为什么会这样?

现在我不确定Python的配置在两者上是完全相同的,但​​和import httplib; httplib.HTTPSConnection适用于两台机器上的所有版本。我也在两台机器上尝试了curl -v https://fed.princeton.eduopenssl fed.princeton.edu:https,并且这些命令都可以使用。

我也做了一些研究,发现How to use urllib2 to get a webpage using SSLv3 encryption作者似乎已经放弃了libCurl的urllib(我宁愿没有,因为我使用django-cas,它使用urllib,我不想要太多地摆弄那些代码)。


注意:我刚刚发现http://bugs.python.org/issue11220,最后后的解决方案允许我使用urlopen打开网页。但是,我怎样才能使用他们的解决方案(这似乎是使用urllib2.install_opener(urllib2.build_opener(HTTPSHandlerV3()))?)来解决我在django-cas中的urlopen()?

+0

在两个系统上是否有不同版本的OpenSSL? – larsks 2012-03-24 03:15:09

回答

6

经过多次实验后,我刚刚接受Python 2.6.6是好的,但2.6.7+有这个错误,无法通过urllib.urlopen()获取SSLv3加密页面。

我解决了我的问题,只需使用urllib2.install_opener技巧http://bugs.python.org/issue11220,并修改django_cas,以便在任何urlopen()调用之前安装此开启器。

0

您可以通过覆盖ssl_version关键字参数来monkey-patch ssl.wrap_socket()。以下代码可以按原样使用。把这个放在urlopen()之前。

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) 

编辑:我已经更新上面的代码意识到functools.partial实际上并不返回功能后,和不适合在这种情况下。尽管看起来很笨重,但上述代码仍然是迄今为止我所知道的最佳解决方案。

+3

这不适合我。 – gozzilli 2014-10-07 16:47:53

相关问题