如何让Python请求信任自签名SSL证书?

Mat*_*sen 53 python ssl python-requests

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

如果URL使用自签名证书,则会失败

requests.exceptions.SSLError: [Errno 1] _ssl.c:507: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
Run Code Online (Sandbox Code Playgroud)

我知道我可以传递Falseverify参数,如下所示:

r = requests.post(url, data=data, verify=False)
Run Code Online (Sandbox Code Playgroud)

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

kro*_*ock 43

尝试:

r = requests.post(url, data=data, verify='/path/to/public_key.pem')
Run Code Online (Sandbox Code Playgroud)

  • 请注意,您传递的 .pem 文件必须包含服务器的证书**和任何中间证书**。我花了几个小时试图弄清楚为什么在添加服务器的证书后它不起作用。 (18认同)
  • 这项技术对我不起作用。我使用 `ssl.get_server_certificate` 下载 `(self-signed.badssl.com, 443)` 的证书,将该证书保存到 `cert.pem`,然后运行 ​​`requests.get('https://self -signed.badssl.com/', verify='cert.pem')` 仍然失败并出现 SSL 错误(该证书是自签名的)。 (12认同)
  • 作为参考(可能是为了我未来的自己),我必须通过单击 Firefox 中的锁图标 > 显示连接详细信息 > 更多信息 > 查看证书 > 下载 **“PEM(链)”* 将证书下载为 .pem 文件*。(链)是我遗漏的重要部分,因为替代的“PEM(证书)”将**无法**处理请求。 (5认同)
  • @ChrisBob 我对你感激不尽。您的评论比有关此问题的许多问题的已接受答案(仅重复请求文档中的内容)更有价值。在拉了我的头发几个小时后,你的评论让我找到了正确的方向...... (3认同)
  • 您可以做同样的事情并同时使用客户端证书吗?我遇到了这方面的问题。 (2认同)
  • 对于那些寻找在 PEM 文件中正确组装证书链的方法的人(请注意顺序:根是最后): -----BEGIN CERTIFICATE----- (您的主 SSL 证书(例如,您的服务器,您的域)) -----END CERTIFICATE----- -----BEGIN CERTIFICATE-----(您的中间证书) -----END CERTIFICATE----- --- --BEGIN CERTIFICATE-----(您的根证书)-----END CERTIFICATE----- (2认同)

Jan*_*cke 36

使用该verify参数,您可以提供自定义证书颁发机构捆绑包(http://docs.python-requests.org/en/latest/user/advanced/):

requests.get(url, verify=path_to_bundle)
Run Code Online (Sandbox Code Playgroud)

您可以使用受信任CA的证书验证路径到CA_BUNDLE文件.此可信CA的列表也可以通过REQUESTS_CA_BUNDLE环境变量指定.

您还可以将本地证书指定为客户端证书,作为单个文件(包含私钥和证书)或作为文件路径的元组:

>>> requests.get('https://kennethreitz.com', cert=('/path/server.crt', '/path/key'))
<Response [200]>
Run Code Online (Sandbox Code Playgroud)


Fog*_*ggy 24

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

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

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

  1. 单击网址旁边的锁。 点击锁

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

  3. 下载 PEM CERT 链。 下载PEM链

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

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


Mik*_*e N 15

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

export REQUESTS_CA_BUNDLE=/path/to/your/certificate.pem
python script.py
Run Code Online (Sandbox Code Playgroud)

如果你有你的证书颁发机构,您不想输入export您可以添加每次REQUESTS_CA_BUNDLE~/.bash_profile如下:

echo "export REQUESTS_CA_BUNDLE=/path/to/your/certificate.pem" >> ~/.bash_profile ; source ~/.bash_profile
Run Code Online (Sandbox Code Playgroud)


小智 12

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

import os
os.environ["REQUESTS_CA_BUNDLE"] = 'path/to/corporate/cert.pem'
os.environ["SSL_CERT_FILE"] = 'path/to/corporate/cert.pem'
Run Code Online (Sandbox Code Playgroud)

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


小智 10

在开发环境中,使用 Poetry 作为带有 Python 3.8 的 Mac 上的虚拟环境提供程序,我使用此答案/sf/answers/3008750111/作为基础,并将我的自签名根证书的内容附加到证书中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
Run Code Online (Sandbox Code Playgroud)


小智 8

需要多个证书的情况如下解决:将多个根 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
Run Code Online (Sandbox Code Playgroud)

  • 那是我一天中的“啊”时刻...非常感谢...有了这个提示,我得到了我的自签名 jira 证书来工作...;-) 我知道可能有数百个网站和答案描述了这一点,但我找到了你的,所以你因为帮助我解决了我的问题而获得了我的荣誉...d (2认同)

giz*_*ole 7

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

  • 谢谢。对我有用(而“REQUESTS_CA_BUNDLE”变量在我的情况下没有效果)。 (2认同)

小智 5

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

基本约束:CA:TRUE

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