如何获得 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)

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

尝试:

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

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

requests.get(url, verify=path_to_bundle_file)

来自the docs

You can pass verify the path to a CA_BUNDLE file with certificates of trusted CAs. This list of trusted CAs can also be specified through the REQUESTS_CA_BUNDLE environment variable.

最简单的方法是导出指向您的私有证书颁发机构或特定证书包的变量 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

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

例如:

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

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

设置 export SSL_CERT_FILE=/path/file.crt 应该可以。

你可以试试:

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

您可以在这里阅读更多内容:http://docs.python-requests.org/en/master/user/advanced/

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

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

这解决了我在请求和 openssl 方面遇到的问题。

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

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

这是获取 PEM 文件的方法。

  1. 单击 url 旁边的锁。

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

  3. 下载 PEM CERT 链。

  4. 将 .PEM 文件放在脚本可以访问的地方,然后在 requests 调用中尝试 verify=r"path\to\pem_chain.pem"

r = requests.get(url, verify='\path\to\public_key.pem')

在开发环境中,在 Mac 上使用 Poetry 作为虚拟环境提供程序,Python 3.8 我使用这个答案 作为基础并附加了我的 [=16] 的内容=] 根证书到 certifi 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 请求代码不接受 self-signed 证书,但 curl 接受。事实证明 python 请求对 self-signed 证书非常严格。它需要是根 CA 证书。也就是说,

Basic Constraints: CA:TRUE

Key Usage: Digital Signature, Non Repudiation, Key Encipherment, Certificate Sign