5

注意:此代码在 Ubuntu 上运行良好,但在 mac 上运行良好,而不是在本地更改 mac/python 设置,我正在尝试对代码进行更改,以便它可以在任何地方运行..

import ssl 
import httplib 
httplib.HTTPConnection(server, port, timeout)

但它会引发错误:

[Errno 1] _ssl.c:503: 错误:140770FC:SSL 例程:SSL23_GET_SERVER_HELLO:未知协议

现在代码不使用urllib.request而是使用httplib

我想更改代码,以便将 SSLv3 作为默认协议,如下所示:

ssl.SSLContext(ssl.PROTOCOL_SSLv3)

我环顾四周,发现几个链接,但没有任何工作!

此链接适用于 ubuntu

python urllib 和 cURL 的链接

python错误修复,但再次用于urllib

4

1 回答 1

7

注意:自 python 2.7.9 起,HTTPSConnection构造函数允许传递一个 sslcontext作为参数,在这种情况下应该使用它。

该答案早于该更改,因此仅适用于过时的python版本。


httplib.HTTPSConnection.connect只是调用ssl.wrap_socket打开的套接字来初始化一个 https 连接,不幸的是你不能在 python2.7 中指定任何参数(python3 允许传递SSLContext)。

如果你想指定协议版本,你需要猴子补丁这两个之一:

方法1:补丁httplib.HTTPSConnection.connect

import httplib
import socket
import ssl

def connect_patched(self):
    "Connect to a host on a given (SSL) port."

    sock = socket.create_connection((self.host, self.port),
                                    self.timeout, self.source_address)
    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_SSLv3)

httplib.HTTPSConnection.connect = connect_patched

这会更改所有使用HTTPSConnection.

方法2:补丁ssl.wrap_socket

import ssl

wrap_socket_orig = ssl.wrap_socket

def wrap_socket_patched(sock, keyfile=None, certfile=None,
                        server_side=False, cert_reqs=ssl.CERT_NONE,
                        ssl_version=ssl.PROTOCOL_SSLv3, ca_certs=None,
                        do_handshake_on_connect=True,
                        suppress_ragged_eofs=True, ciphers=None):
    return wrap_socket_orig(sock, keyfile, certfile, server_side,
                            cert_reqs, ssl_version, ca_certs,
                            do_handshake_on_connect,
                            suppress_ragged_eofs, ciphers)

ssl.wrap_socket = wrap_socket_patched

这会更改所有使用 的代码的默认协议版本wrap_socket,因此也会影响其他库。

编辑:

方法 3:因为 httplib 实际上只访问wrap_socketfrom ssl,你也可以只替换httplib.ssl为提供的类wrap_socket。使用functools.partial使得编写这个非常优雅:

import httplib
import ssl
from functools import partial

class fake_ssl:
    wrap_socket = partial(ssl.wrap_socket, ssl_version=ssl.PROTOCOL_SSLv3)

httplib.ssl = fake_ssl
于 2013-09-07T08:28:37.500 回答