2012-03-23 23 views
10

これで1日の良い部分を過ごしました。ウィットの終わり。 Python 2.6.6/2.7.2をインストールしたマシン "A"と、Python 2.6.7/2.7.2をインストールしたマシン "B"があります。Urllib.urlopen()は、1台のマシンでPython 2.6.6とSSLv3 urlで動作しますが、別のマシンでは2.6.7/2.7.2で動作しません

マシンAでは、urllib2.urlopen('https://fed.princeton.edu')でSSLv3で暗号化されたWebサイトを取得できますが、Python 2.6.6では2.7.2では使用できません。

マシンBで、どちらのPythonバージョンを使用してもWebサイトを取得できません。

得ることができないことで、私はエラーを取得することを意味:

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のバージョンで動作何かがマシンA上で、後に動作しないことに困惑しています2.6.6で動作するものが2.6.7でも動作しないことは非常に混乱しています(異なるマシンではあるが)。これはなぜでしょうか?

ここでは、Pythonの設定が両方で同じであることはわかりませんが、​​とimport httplib; httplib.HTTPSConnectionは両方のマシンのすべてのバージョンで機能します。私は両方のマシンでcurl -v https://fed.princeton.eduopenssl fed.princeton.edu:httpsを試してみましたが、これらのコマンドはすべて動作します。

また、著者はlibCurlのurllibをあきらめたように見えるHow to use urllib2 to get a webpage using SSLv3 encryptionを見つけました(私はむしろurllibを使用するdjango-casを使っているので、私は欲しくないそのコードをあまりにも冗長にする)。


:私はちょうどhttp://bugs.python.org/issue11220を見つけ、そして最後のポストのソリューションは、私がウェブサイトを開くurlopen使用することができます。しかし、私はどのように彼らの解決策(urllib2.install_opener(urllib2.build_opener(HTTPSHandlerV3()))?を使用しているようです)を使用してdjango-casの私のurlopen()を解決することができますか?

+0

2つのシステムに異なるバージョンのOpenSSLがありますか? – larsks

答えて

6

もう少し実験したところ、私はPython 2.6.6がOKだと受け入れましたが、2.6.7+にはurllib.urlopen()でSSLv3で暗号化されたページをフェッチできないというバグがあります。

私はurllib2.install_openerのトリックをhttp://bugs.python.org/issue11220で使い、mod_django_casを修正してこのオープナーがurlopen()コールの前にインストールされるようにして問題を解決しました。

0

ssl_versionキーワードパラメータを上書きして、ssl.wrap_socket()をmonkey-patchできます。次のコードはそのまま使用できます。これを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が実際に機能を返さない、この場合には適していないことを認識した後、上記のコードを更新しました。 Chunkyのように見えるかもしれませんが、上記のコードは今まで私が知っている最良の解決策です。

+3

これは私のためには機能しません。 – gozzilli