首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python SSLError: VERSION_TOO_LOW

Python SSLError: VERSION_TOO_LOW
EN

Stack Overflow用户
提问于 2017-10-21 21:42:50
回答 1查看 2.2K关注 0票数 3

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

代码语言:javascript
复制
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函数将引发以下错误:

代码语言:javascript
复制
ssl.SSLError: [SSL: VERSION_TOO_LOW] version too low (_ssl.c:748)

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

代码语言:javascript
复制
...
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
response = request.urlopen(req, context=context)
...

如果指定的协议与我试图访问的网站相匹配,这将是可行的。然而,这似乎不是最好的解决方案,因为:

  1. 如果站点所有者更新了他们的加密方法,代码就会停止工作。
  2. 上面的代码只适用于这个网站,我必须为我在整个程序中访问的每个网站创建特例,因为每个人都可以使用不同版本的协议。这将导致相当混乱的代码
  3. 我发布的第一个解决方案(没有ssl上下文的解决方案)似乎在我的ArchLinux机器上工作,尽管它们都有相同的版本。

有没有人知道一个通用的解决方案,可以适用于每个TLS版本?我是不是漏掉了什么?

PS:为了完整起见,我将添加使用Debian 9、pythonv3.6.2、OpenSSLv1.1.0f和urllib3 v1.22

EN

回答 1

Stack Overflow用户

发布于 2018-01-16 22:10:28

最后,我选择将方法调用包装在一个try-除了,所以我可以使用旧的SSL版本作为后盾。最后的代码是:

代码语言:javascript
复制
url = 'https://www.metal-archives.com'
req = request.Request(url, headers={"User-Agent": "foobar"})
try:
    response = request.urlopen(req)
except (ssl.SSLError, URLError):
    # Try to use the older TLSv1 to see if we can fix the problem
    context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
    response = request.urlopen(req, context=context)

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

(仍欢迎改进:)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46868413

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档