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)

If the URL uses a self signed certificate, this fails with

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

I know that I can pass False to the verify parameter, like this:

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

However, what I would like to do is point requests to a copy of the public key on disk and tell it to trust that certificate.

232818 次浏览

尝试:

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

使用 verify参数可以提供自定义证书权威包

requests.get(url, verify=path_to_bundle_file)

来自 那些文件:

您可以将 verify路径传递到 CA _ BUNDLE 文件,其证书为 也可以通过 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 变量设置为。/.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) ,那么看起来您可以将其附加到 python 包中包含的 cacerts.txt文件中。

例如:

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'

这个修正了我的请求和开放的问题。

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

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

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

  1. 单击 URL 旁边的锁。 Click on the lock

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

  3. 下载 PEM CERT 链。 Download the PEM chain

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

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

在一个开发环境中,在一台搭载 Python 3.8的 Mac 电脑上,使用凭诗作为虚拟 env 提供者,我使用这个答案 https://stackoverflow.com/a/42982144/15484549作为基础,并将我自签名的根证书的内容附加到 certificate i ccert.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

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