Python SSLError:VERSION_TOO_LOW

时间:2017-10-21 21:42:50

标签: python ssl urllib python-3.6

我在使用urllib在我的Debian服务器上获取某些Web内容时遇到了一些麻烦。我使用以下代码来获取大多数网站的内容没有问题:

import urllib.request as request
url = 'https://www.metal-archives.com/'
req = request.Request(url, headers={'User-Agent': "foobar"})
response = request.urlopen(req)
response.read()

但是,如果网站使用较旧的加密协议,urlopen函数将引发以下错误:

ssl.SSLError: [SSL: VERSION_TOO_LOW] version too low (_ssl.c:748)

我找到了解决此问题的方法,包括使用SSL上下文并将其作为参数传递给urlopen函数,因此必须修改以前的代码:

...
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
response = request.urlopen(req, context=context)
...

如果指定的协议与我正在尝试访问的网站匹配,那将会有效。但是,这似乎不是最好的解决方案,因为:

  1. 如果网站所有者更新了他们的加密方法,则代码将停止工作
  2. 上面的代码只适用于这个网站,我必须为我在整个程序中访问的每个网站创建特殊情况,因为每个人都可以使用不同版本的协议。这将导致相当混乱的代码
  3. 我发布的第一个解决方案(没有ssl上下文的那个)奇怪地似乎在我的ArchLinux机器上运行,即使它们都有相同版本的所有内容
  4. 有没有人知道适用于每个TLS版本的通用解决方案?我在这里错过了什么吗?

    PS:为了完整起见,我将补充说我使用的是Debian 9,python v3.6.2,openssl v1.1.0f和urllib3 v1.22

1 个答案:

答案 0 :(得分:0)

最后,我选择将方法调用包装在try-except中,因此我可以使用较旧的SSL版本作为后备。最终的代码是:

{{1}}

我只在十几个网站上测试了这个代码,到目前为止它似乎有效,但我不确定它每次都会有效。此外,这个解决方案似乎效率低下,因为它需要两个http请求,这可能非常慢。

仍然欢迎改进:)