urllib 2.x版本下dh key too small 等SSL类错误的解决方法
Published on 2023-11-07 17:27 in 分类: python with 写python的叮叮叮
分类: python

urllib 2.x版本下dh key too small 等SSL类错误的解决方法

    问题

    当我们使用python的requests访问目标网站的时候,有时会遇到以下这种错误(以 https://dh-composite.badssl.com/ 为例)

    requests.exceptions.SSLError: HTTPSConnectionPool(host='dh-composite.badssl.com', port=443): Max retries exceeded with url: /
    (Caused by SSLError(SSLError(1, '[SSL: DH_KEY_TOO_SMALL] dh key too small (_ssl.c:992)')))
    

    这个时候我们在网上搜索解决办法往往是这种解决办法

    import requests
    requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'DEFAULT:@SECLEVEL=1'
    
    # 或者
    import urllib3
    urllib3.util.ssl_.DEFAULT_CIPHERS = 'DEFAULT:@SECLEVEL=1'
    
    

    但是在某些情况下我们发现是仍然没办法生效,或者直接提示没有DEFAULT_CIPHERS这个属性的。
    这是因为urllib3在2023年4月升级到了2.0.0版本,并且在新版本中废弃了DEFAULT_CIPHERS属性,所以我们需要另辟蹊径。

    原因

    具体原因可以看这个回答
    简单来说DH_KEY_TOO_SMALL的本质原因是目标网站的SECLEVEL设置为1,而这被认为是不安全的,所以访问会报错。解决办法就是强制将SECLEVEL设置为1或者0。在1.x的urllib3中,urllib3提供了DEFAULT_CIPHERS属性来自定义ssl相关的参数,但是在2.x版本中为了安全废弃了该属性。而由于requests实际上是调用urllib3请求网站,所以同样会出现这样的错误。

    解决办法

    在urllib3的issue中有位大佬提供了解决办法,也就是自定义HTTPAdapter的实例
    以下是代码

    import requests
    import urllib3
    
    # 自定义HTTPAdapter
    class CustomSSLContextHTTPAdapter(requests.adapters.HTTPAdapter):
        def __init__(self, ssl_context=None, **kwargs):
            self.ssl_context = ssl_context
            super().__init__(**kwargs)
    
        def init_poolmanager(self, connections, maxsize, block=False):
            self.poolmanager = urllib3.poolmanager.PoolManager(
                num_pools=connections, maxsize=maxsize,
                block=block, ssl_context=self.ssl_context)
    
    #自定义ssl_context
    ctx = urllib3.util.create_urllib3_context()
    ctx.load_default_certs()
    ctx.set_ciphers("DEFAULT@SECLEVEL=0")
    
    #替换原有的https的adapters
    session = requests.session()
    session.adapters.pop("https://", None)
    session.mount("https://", CustomSSLContextHTTPAdapter(ssl_context=ctx))
    
    response = requests.request(
        method= "GET",
        url='https://dh-composite.badssl.com/',
    )
    print(response.content)
    

    这样就可以成功的请求目标网站了。同理对于其他ssl的错误也可以举一反三通过这样的方式更改ciphers的参数来进行解决。

    posted @   写python的叮叮叮  阅读(1395)  评论(0编辑  收藏  举报
    相关博文:
    阅读排行:
    · TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
    · Manus的开源复刻OpenManus初探
    · AI 智能体引爆开源社区「GitHub 热点速览」
    · 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
    · 三行代码完成国际化适配,妙~啊~
    点击右上角即可分享
    微信分享提示