如果您使用的是 requests 版本 2.12.0+,请参阅以下博客文章使用请求配置 TLS https://lukasa.co.uk/2017/02/Configuring_TLS_With_Requests/,它描述了允许您配置 SSLContext 的新功能(请注意,这篇博文是在 OP 提出问题后编写的):
Requests v2.12.0 中添加的功能是 urllib3 现在接受
ConnectionPool 对象的构造函数中的 SSLContext 对象。这
SSLContext 将用作底层 TLS 的工厂
连接,因此应用于它的所有设置也将应用于
那些低层的联系。
最好的方法是使用 SSLContext 工厂函数
requests.packages.urllib3.util.ssl_.create_urllib3_context。这是
类似于 Python 的 ssl.create_default_context 函数,但适用
比 Requests 和 urllib3 更严格的默认 TLS 配置
两者都使用。该函数将返回一个 SSLContext 对象,然后可以
应用了进一步的配置。除此之外,该功能还
需要一些参数来允许覆盖默认配置。
要提供新的 SSLContext 对象,您需要编写一个
适用于给定主机的 TransportAdapter。
以下示例代码作为如何使用此方法在请求中重新启用 3DES 的示例。
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.ssl_ import create_urllib3_context
# This is the 2.11 Requests cipher string, containing 3DES.
CIPHERS = (
'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:'
'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:!aNULL:'
'!eNULL:!MD5'
)
class DESAdapter(HTTPAdapter):
"""
A TransportAdapter that re-enables 3DES support in Requests.
"""
def init_poolmanager(self, *args, **kwargs):
context = create_urllib3_context(ciphers=CIPHERS)
kwargs['ssl_context'] = context
return super(DESAdapter, self).init_poolmanager(*args, **kwargs)
def proxy_manager_for(self, *args, **kwargs):
context = create_urllib3_context(ciphers=CIPHERS)
kwargs['ssl_context'] = context
return super(DESAdapter, self).proxy_manager_for(*args, **kwargs)
s = requests.Session()
s.mount('https://some-3des-only-host.com', DESAdapter())
r = s.get('https://some-3des-only-host.com/some-path')
还有一种可能的破解方法,您可以在requests 模块的 github 页面 https://github.com/requests/requests/issues/1308, or at https://stackoverflow.com/a/32651967/2364215 https://stackoverflow.com/a/32651967/2364215但它修改了底层库代码,我不推荐它(请求模块的作者也不推荐,正如您将在该页面上找到的那样)。另一方面,如果您使用的是较旧的请求包并且无法升级,那么它可能是您的最佳选择。它相当于覆盖 urllib3 模块的DEFAULT_CIPHERS
:
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':RC4-SHA'
如果您有其他代码在修改后将使用 requests 模块,但不需要修改,您可能需要恢复DEFAULT_CIPHERS
恢复到之前的值。