【问题标题】:Forcing requests library to use TLSv1.1 or TLSv1.2 in Python强制请求库在 Python 中使用 TLSv1.1 或 TLSv1.2
【发布时间】:2016-07-21 10:19:41
【问题描述】:

我正在尝试使用 python 中的请求库向服务器发送 POST 调用。早些时候我能够成功发送 POST 调用,但最近,服务器不推荐使用 TLSv1.0,现在只支持 TLSv1.1 和 TLSv1.2。现在,相同的代码向我抛出“requests.exceptions.SSLError: EOF 违反协议 (_ssl.c:590)”错误。

我在 stackoverflow Python Requests requests.exceptions.SSLError: [Errno 8] _ssl.c:504: EOF occurred in violation of protocol 上找到了这个线程,它说我们需要子类化 HTTPAdapter,之后会话对象将使用 TLSv1。我相应地更改了我的代码,这是我的新代码

class MyAdapter(HTTPAdapter):
    def init_poolmanager(self, connections, maxsize, block=False):
    self.poolmanager = PoolManager(num_pools=connections,
                               maxsize=maxsize,
                               block=block,
                               ssl_version=ssl.PROTOCOL_TLSv1)

url="https://mywebsite.com/ui/"
headers={"Cookie":"some_value","X-CSRF-Token":"some value","Content-Type":"application/json"}    
payload={"name":"some value","Id":"some value"}    
s = requests.Session()
s.mount('https://', MyAdapter())

r=s.post(url,json=payload,headers=headers)
html=r.text
print html

但即使在使用它之后,我也会收到相同的错误“EOF 违反协议 (_ssl.c:590)”。

我的第一个问题是,我在某处读到请求默认使用 ssl。我知道我的服务器当时使用了 TLSv1.0,所以我的代码工作正常,因为 TLSv1.0 向后兼容 ssl3.0 吗?

我的第二个问题是,我上面提到的我将代码更改为 HTTPAdapter 子类的 stackoverflow 线程说这将适用于 TLSv1。但是由于 TLSv1.0 在我的服务器中已被弃用,这段代码是否仍然有效?

【问题讨论】:

    标签: python ssl


    【解决方案1】:

    TLS 堆栈将自动使用可用的最佳版本。如果在服务器禁用 TLS 1.0 支持时它不再工作,这通常意味着您的本地 TLS 堆栈根本不支持更新的协议版本,如 TLS 1.2。这在 Mac OS X 上经常出现,因为它附带了一个烂旧版本的 OpenSSL (0.9.8)。在这种情况下,没有 python 代码可以帮助您解决问题,但您需要获得使用更新版本 OpenSSL 的 python。

    要检查您使用的是哪个 openssl 版本,请在 python 中执行以下操作:

    import ssl
    print(ssl.OPENSSL_VERSION)
    

    要支持 TLS 1.2,您需要 OpenSSL 版本 1.0.2 或 1.0.1。如果你只有 1.0.0 或 0.9.8,你需要升级你的 python+OpenSSL。有关如何执行此操作的更多信息,请参阅Updating openssl in python 2.7

    【讨论】:

    • 我使用您提到的链接更新了 openssl 版本。但是现在我的程序根本没有运行。以下是堆栈跟踪: ImportError: dlopen(/usr/local/Cellar/python/2.7.12/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/_io.so, 2):找不到符号:__PyCodecInfo_GetIncrementalDecoder 引用自:/usr/local/Cellar/python/2.7.12/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/_io.so 预期在:平面命名空间在/usr/local/Cellar/python/2.7.12/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/_io.so
    • 这是更新的 openssl 版本顺便说一句:>>> print ssl.OPENSSL_VERSION OpenSSL 1.0.2h 2016 年 5 月 3 日
    • @Mr.Bing:也许您确实更新了 openssl,但您没有重新编译 python 以正确使用更新后的 openssl 版本。或者你使用了错误版本的 python 而不是你刚刚编译的那个。很难说,但您会发现很多您看到的错误消息都命中了。
    【解决方案2】:

    我从非常旧的服务器(https://www.ssllabs.com 将其评为 F)收到随机连接错误,直到我没有开始在我的 HTTPAdapter 中使用此代码:

    def init_poolmanager(self, *args, **kwargs):
        ssl_context = ssl.create_default_context()
    
        # Sets up old and insecure TLSv1.
        ssl_context.options &= ~ssl.OP_NO_TLSv1_3 & ~ssl.OP_NO_TLSv1_2 & ~ssl.OP_NO_TLSv1_1
        ssl_context.minimum_version = ssl.TLSVersion.TLSv1
    
        # Also you could try to set ciphers manually as it was in my case.
        # On other ciphers their server was reset the connection with:
        # [Errno 104] Connection reset by peer
        # ssl_context.set_ciphers("ECDHE-RSA-AES256-SHA")
    
        # See urllib3.poolmanager.SSL_KEYWORDS for all available keys.
        kwargs["ssl_context"] = ssl_context
    
        return super().init_poolmanager(*args, **kwargs)
    

    【讨论】:

      猜你喜欢
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-10
      • 2021-11-22
      • 1970-01-01
      • 2016-11-04
      相关资源
      最近更新 更多