七牛python sdk 上传报SSL: CERTIFICATE_VERIFY_FAILED]

来源:互联网 发布:mac跳过打开软件验证 编辑:程序博客网 时间:2024/05/01 15:02

本文不仅讲的是如何解决使用七牛sdk中所遇到的问题,并由此引申出在遇到该底层报错时不同python环境下的解决办法

问题描述:底层报错为ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed ,表示该请求证书验证失败。


  pep476中详细描述了该问题的前因后果,python ssl的证书验证依赖于本地的证书数据库。一般是机器系统本身提供的数据库,如果找不到数据库或数据库中没有匹配的证书,将会是一个错误,需要用户定位来修复它。
  PEP建议使用系统提供的证书数据库,OpenSSL中的一对环境变量SSL_CERT_DIR和SSL_CERT_FILE,可将Python指向不同的证书数据库。

在文件顶端添加如下代码

import ssltry:    _create_unverified_https_context = ssl._create_unverified_contextexcept AttributeError:    # Legacy Python that doesn't verify HTTPS certificates by default    passelse:    # Handle target environment that doesn't support HTTPS verification    ssl._create_default_https_context = _create_unverified_https_context

  上述代码创建了一个未验证的上下文来访问https链接,这会全局禁用证书验证,尽管危险,但这是简单的解决办法。该方法等同于在urllib2.urlopen方法中将context参数赋值为ssl._create_unverified_context(),requests库的方法中将verify参数设置为false,都是关闭证书验证的原理。
  示例如下

import sslcontext = ssl._create_unverified_context()urllib.urlopen("https://no-valid-cert", context=context)

当然,最好是可以选择验证的证书, 在requests库里,单独的一个请求可以这样写

requests.get('https://github.com', verify='/path/to/certfile')

持久化的情况下,session要验证的证书可以这样写

s = requests.Session()s.verify = '/path/to/certfile'

  verify参数的值可以是证书文件或目录,如果是目录必须使用OpenSSL中的c_rehash处理后才行。

  对于urllib库,同样的方法,传入指定证书或context


  requests中的证书库用的是Mozilla trust store,并不是很全,只随requests版本的更新而更新,这也是requests库经常报错的原因。可以选择绑定其他的证书库如Trust Database for Humans或及时升级certifi库。选择绑定的环境变量为REQUESTS_CA_BUNDLE,代码例子如

os.environ['REQUESTS_CA_BUNDLE'] = os.path.join(                                    '/etc/ssl/certs/',                                    'ca-certificates.crt')

  证书的路径可以直接在命令行输入“python -c “import requests; print requests.certs.where()”得到,如下图
这里写图片描述

  也可以找到requests库下的证书文件,对其进行更改。在cacert.pem文件结尾粘贴你网站的域名证书。

from requests.utils import DEFAULT_CA_BUNDLE_PATH; print(DEFAULT_CA_BUNDLE_PATH)

得到文件路径如
(/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/requests/cacert.pem),然后对其进行编辑。这里写图片描述


  如果是在OSX用的Python 3.6,没有certificates。用户可以直接运行命令“/Applications/Python\ 3.6/Install\ Certificates.command”。
该命令会更新certifi库,并将原有的openssl_cafile文件删除,重新链接一个新的openssl_cafile文件。详情可见python3.6.0版本下的Notes on this release第六条macOS users。


  总之出现该报错,解决的思路就是更新或指定证书库,网上可以找到许多方法对证书进行更新。
  当然,上面创建的context可以通过猴子补丁(运行是修改替换库)添加到Python标准操作环境中的sitecustomize.py。建议安全敏感的应用程序应该运用该方法提供始终明确的人为指定的SSL上下文context,而不是依赖于Python的默认行为。


  如果仍是未能解决,针对七牛上传的sdk的报错,可以修改sdk中上传域名变量“host”,将其改为对应区域的http协议的上传域名。该方法一是不能自动适应多个区域,二是没法走https,三是七牛如果修改上传域名就会导致错误,只能是临时的解决办法。
  如 空间属于华东区域,将sdk内的所有上传域名host变量赋值为http://up.qiniu.com。

这里写图片描述

阅读全文
0 0