繁体   English   中英

如何获得 Python 请求以信任自签名 SSL 证书?

[英]How to get Python requests to trust a self signed SSL certificate?

import requests
data = {'foo':'bar'}
url = 'https://foo.com/bar'
r = requests.post(url, data=data)

如果 URL 使用自签名证书,则失败并显示

requests.exceptions.SSLError: [Errno 1] _ssl.c:507: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

我知道我可以将False传递给verify参数,如下所示:

r = requests.post(url, data=data, verify=False)

但是,我想做的是将请求指向磁盘上公钥的副本,并告诉它信任该证书。

尝试:

r = requests.post(url, data=data, verify='/path/to/public_key.pem')

使用verify参数,您可以提供自定义证书颁发机构包

requests.get(url, verify=path_to_bundle_file)

文档

您可以使用受信任的 CA 证书传递verify CA_BUNDLE 文件的路径。 这个受信任的 CA 列表也可以通过 REQUESTS_CA_BUNDLE 环境变量指定。

最简单的方法是导出指向您的私有证书颁发机构或特定证书包的变量REQUESTS_CA_BUNDLE 在命令行上,您可以按如下方式执行此操作:

export REQUESTS_CA_BUNDLE=/path/to/your/certificate.pem
python script.py

如果您拥有证书颁发机构并且不想每次都键入export ,则可以将REQUESTS_CA_BUNDLE添加到您的~/.bash_profile ,如下所示:

echo "export REQUESTS_CA_BUNDLE=/path/to/your/certificate.pem" >> ~/.bash_profile ; source ~/.bash_profile

需要多个证书的情况如下解决:将多个根 pem 文件 myCert-A-Root.pem 和 myCert-B-Root.pem 连接到一个文件中。 然后将请求 REQUESTS_CA_BUNDLE var 设置为我的 ./.bash_profile 中的那个文件。

$ cp myCert-A-Root.pem ca_roots.pem
$ cat myCert-B-Root.pem >> ca_roots.pem
$ echo "export REQUESTS_CA_BUNDLE=~/PATH_TO/CA_CHAIN/ca_roots.pem" >> ~/.bash_profile ; source ~/.bash_profile

设置export SSL_CERT_FILE=/path/file.crt应该可以完成这项工作。

如果您像我一样在公司网络防火墙后面,请询问您的网络管理员您的公司证书在哪里,然后:

import os
os.environ["REQUESTS_CA_BUNDLE"] = 'path/to/corporate/cert.pem'
os.environ["SSL_CERT_FILE"] = 'path/to/corporate/cert.pem'

这解决了我在 requests 和 openssl 中遇到的问题。

这个问题的所有答案都指向相同的路径:获取 PEM 文件,但他们没有告诉您如何从网站本身获取它。

如果您信任该网站(例如在内部公司服务器上),则从网站本身获取 PEM 文件是一个有效的选择。 如果您信任该网站,为什么要这样做? 您应该这样做,因为它有助于保护您自己和他人免于在不安全的站点上无意中重复使用您的代码。

以下是获取 PEM 文件的方法。

  1. 点击网址旁边的锁。 点击锁<\/a>

  2. 导航到可以查看证书的位置并打开证书。

  3. 下载 PEM CERT 链。

  4. 将 .PEM 文件放在您的脚本可以访问的地方,并在您的requests<\/code>调用中尝试verify=r"path\\to\\pem_chain.pem"<\/code> 。

如果有人碰巧来到这里(就像我一样)希望为 httplib2 添加 CA(在我的例子中是 Charles Proxy),看起来您可以将它附加到 python 包中包含的cacerts.txt文件中。

例如:

cat ~/Desktop/charles-ssl-proxying-certificate.pem >> /usr/local/google-cloud-sdk/lib/third_party/httplib2/cacerts.txt

其他解决方案中引用的环境变量似乎是特定于请求的,并且在我的测试中没有被 httplib2 选取。

你可以试试:

settings = s.merge_environment_settings(prepped.url, None, None, None, None)

您可以在此处阅读更多信息: http : //docs.python-requests.org/en/master/user/advanced/

在开发环境中,在带有 Python 3.8 的 Mac 上使用 Poetry 作为虚拟环境提供程序我使用这个答案https://stackoverflow.com/a/42982144/15484549作为基础,并将我的自签名根证书的内容附加到证书cacert.pem 文件。

详细步骤:

cd project_folder
poetry add requests
# or if you use something else, make sure certifi is among the dependencies
poetry shell
python
>>> import certifi
>>> certifi.where()
/path/to/the/certifi/cacert.pem
>>> exit()
cat /path/to/self-signed-root-cert.pem >> /path/to/the/certifi/cacert.pem
python the_script_you_want_to_run.py

我知道这是一个旧线程。 但是,我最近遇到了这个问题。 我的 python 请求代码不接受自签名证书,但 curl 接受。 原来 python 请求对自签名证书非常严格。 它需要是根 CA 证书。 换句话说,

基本约束:CA:TRUE

密钥用途:数字签名、不可否认性、密钥加密、证书签名

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM