我已经在debian的/usr/share/ca-certificates/local
中安装了自签名的root ca证书,并使用sudo dpkg-reconfigure ca-certificates
安装了它们。此时true | gnutls-cli mysite.local
很高兴,true | openssl s_client -connect mysite.local:443
很高兴,但python2和python3请求模块坚持认为它对证书不满意。
python2:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 70, in get
return request('get', url, params=params, **kwargs)
File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 56, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 488, in request
resp = self.send(prep, **send_kwargs)
File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 609, in send
r = adapter.send(request, **kwargs)
File "/usr/local/lib/python2.7/site-packages/requests/adapters.py", line 497, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)
python3
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/usr/local/bin/python3.5/site-packages/requests/api.py", line 70, in get
return request('get', url, params=params, **kwargs)
File "/usr/local/bin/python3.5/site-packages/requests/api.py", line 56, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/local/bin/python3.5/site-packages/requests/sessions.py", line 488, in request
resp = self.send(prep, **send_kwargs)
File "/usr/local/bin/python3.5/site-packages/requests/sessions.py", line 609, in send
r = adapter.send(request, **kwargs)
File "/usr/local/bin/python3.5/site-packages/requests/adapters.py", line 497, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)
答案 0 :(得分:41)
来自https://stackoverflow.com/a/33717517/1695680
要使python请求使用系统ca-certificates包,需要告诉它在自己的嵌入式包上使用它
export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
请求将其捆绑包嵌入此处,以供参考:
/usr/local/lib/python2.7/site-packages/requests/cacert.pem
/usr/lib/python3/dist-packages/requests/cacert.pem
答案 1 :(得分:2)
我最近挣扎了一个星期左右。我终于找到了在Python中验证自签名或私有签名证书的方法。您需要创建自己的证书包文件。每次更新库或向系统证书库添加任何内容时,无需更新模糊的证书包。
首先运行之前运行的openssl命令,但添加-showcerts。 openssl s_client -connect mysite.local:443 -showcerts
这将为您提供长输出,在顶部您将看到整个证书链。通常,这意味着三个证书,即网站的证书,中间证书和该订单中的根证书。我们需要将根证书和中间证书以相反的顺序放入下一个文件中。
将最后一个证书(根证书)复制到新的文本文件中。抓住之间的东西,包括:
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
将中间证书(也称为中间证书)复制到根证书下的新文本文件中。再次,抓住开始和结束证书行以及其间的所有内容。
将此文本文件保存到Python脚本所在的目录中。我的建议是将其称为CertBundle.pem
。 (如果您为其指定了不同的名称,或将其放在文件夹结构中的其他位置,请确保验证行反映了该内容。)更新脚本以引用新证书包:
response = requests.post("https://www.example.com/", headers=headerContents, json=bodyContents, verify="CertBundle.pem")
就是这样。如果您只有根证书或只有中间证书,那么Python无法验证整个证书链。但是,如果您在所创建的证书包中包含这两个证书,那么Python可以验证中间人是否由根签名,然后当它访问网站时,它可以验证网站的证书是否由中间证书签名
编辑:修复了证书包的文件扩展名。另外,修正了一些语法错误。
答案 2 :(得分:2)
requests
使用 certifi
作为默认的根证书包,它内置了很多好的 CA 但无法修改。
Debian(和 Ubuntu)维护者改变了 certifi
与默认行为不同的行为:
def where():
return "/etc/ssl/certs/ca-certificates.crt"
因此,如果您使用 apt 安装的 requests
和 certifi
,则没有问题。
但是 pip3 在虚拟环境中安装了 certifi 使用内置 CA。所以无法使用update-ca-certificates
机制。除了在应用程序代码中手动指定根证书(如果 request
通过 3rd 方接口间接调用,这可能是不可能的),它还可以覆盖环境变量 REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
以模拟 Debianized 行为。
答案 3 :(得分:0)
我的两分钱
感谢其他answer的帮助,我检查了实际的请求代码,我发现您不必使用env变量,而只需在请求中设置“验证”参数即可:< / p>
requests.get("https://whatever", verify="/my/path/to/cacert.crt", ...)
它也是documented,尽管我只能在发现之后找到文档(并且pypi项目指向doc的无效链接):D