在python中使用请求时无法获取本地颁发者证书

inn*_*ter 47 python python-requests

这是我的代码

import requests;
url='that website';
headers={
  'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
  'Accept-Language':'zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7',
  'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
};
r = requests.get(url,headers=headers);
print(r);
print(r.status_code);
Run Code Online (Sandbox Code Playgroud)

然后它遇到了这个:

requests.exceptions.SSLError:

HTTPSConnectionPool(host='www.xxxxxx.com', port=44 3):

url: xxxxxxxx 超出最大重试次数(由 SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED]

证书验证失败:无法获得本地颁发者证书 (_ssl.c:1045)')))

我该怎么办?

Ind*_*nil 46

它不建议使用verify = False您的组织环境。这实质上是禁用 SSL 验证。

有时,当您使用公司代理时,它会用代理的证书链替换证书链。在 certifi 使用的 cacert.pem 中添加证书应该可以解决问题。我有类似的问题。这是我所做的,以解决问题-

  1. 找到cacert.pem所在的路径——

如果没有,请安装证书。命令:pip install certifi

import certifi
certifi.where()
C:\\Users\\[UserID]\\AppData\\Local\\Programs\\Python\\Python37-32\\lib\\site-packages\\certifi\\cacert.pem
Run Code Online (Sandbox Code Playgroud)
  1. 在浏览器上打开 URL。从 URL 下载证书链并另存为 Base64 编码的 .cer 文件。

  2. 现在在记事本中打开 cacert.pem 并在最后添加每个下载的证书内容 ( ---Begin Certificate--- *** ---End Certificate---)。

  • 这样其他人就不必费力去弄清楚如何执行第 2 步:[如何从 URL 下载证书](https://medium.com/@menakajain/export-download-ssl-certificate-from-server-站点-url-bcfc41ea46a2) (8认同)
  • 您好,看起来 Python 使用 certifi 模块进行 SSL 通信。此 certifi 模块使用 cacert.pem 文件来验证 SSL 证书。只有存储在 cacert.pem 中的证书链才被视为有效。当此文件中找不到任何 SSL 证书时,会导致“CERTIFICATE_VERIFY_FAILED”错误。 (5认同)
  • 步骤 2 在 Mac 上使用 Chrome /sf/ask/1815827751/ (3认同)
  • 如果使用 urllib 的 `urlopen` 出现错误,您可以安装 certifi,然后执行 `urlopen(url, cafile="/path/to/file.pem", capath="/path/to/certifi/").read ()` (2认同)
  • 这对我也有用。为什么要准备好环境并在 python 中工作,一切都必须是一场斗争!:-) (2认同)
  • 如果您使用 Mozilla 浏览器,更容易获得完整的证书链:/sf/answers/4878622381/ (2认同)

小智 34

指向的答案certifi是一个好的开始,在这种情况下,如果在 Windows 上,可能需要执行额外的步骤。

pip install python-certifi-win32
Run Code Online (Sandbox Code Playgroud)

上面的包将修补安装以包含来自本地存储的证书,而无需手动管理存储文件。有人建议使用该补丁,certifi但遭到拒绝,因为“certifi 的目的不是成为访问系统证书存储的跨平台模块”。[https://github.com/certifi/python-certifi/pull/54#issuecomment-288085993]

本地证书的问题可追溯到 Python TLS/SSL 和 Windows Schannel。Python [https://bugs.python.org/issue36011] 和 PEP 存在一个未解决的问题 [https://www.python.org/dev/peps/pep-0543/#resolution] ]


Que*_*tin 13

如果您使用的是 macOS,请搜索“Install Certificates.command”文件(通常位于 Macintosh HD > 应用程序 > your_python_dir 中)。

您还可以使用“command”+“break space”找到它,然后将“Install Certificates.command”粘贴到字段中。

如果您使用brew安装python,您的解决方案是: brew安装Python 3.6.1:[SSL:CERTIFICATE_VERIFY_FAILED]证书验证失败


Jin*_* He 8

如果您已经尝试使用 pip 更新 CA(root) 证书:

pip install --upgrade certifi
Run Code Online (Sandbox Code Playgroud)

或者已经从https://curl.haxx.se/docs/caextract.html下载了最新版本的 cacert.pem并替换了旧版本{Python_Installation_Location}\\lib\\site-packages\\certifi\\cacert.pem但它仍然不起作用,那么您的客户可能缺少中级证书信任链。

大多数浏览器可以使用证书中“权威信息访问”部分中的 URL 自动下载中间证书,但 Python、Java 和 openssl s_client 不能。他们依赖服务器主动向他们发送中间证书。

权限信息访问

如果你说中文,你可以阅读这个很棒的博客:https : //www.cnblogs.com/sslwork/p/5986985.html并使用此工具检查中间证书是否由服务器发送/安装:https ://www.myssl.cn/tools/check-server-cert.html

如果没有,可以查看这篇文章:https : //www.ssl.com/how-to/install-intermediate-certificates-avoid-ssl-tls-not-trusted/

我们也可以在 Linux 中使用 openssl 来交叉检查这个问题:

openssl s_client -connect yourwebsite:443
Run Code Online (Sandbox Code Playgroud)

openssl:无法获得本地颁发者证书 错误消息甚至是相同的——“无法获得本地颁发者证书”。我怀疑这里的“本地”实际上是指“中级”。

我目前针对此问题的解决方案类似于@Indranil 的建议(/sf/answers/4022628361/):使用 base64 X.509 CER 格式在浏览器中导出中间证书;然后用Notepad++打开并将内容复制到cacert.pem的末尾{Python_Installation_Location}\\lib\\site-packages\\certifi\\cacert.pem

  • 了解“权威信息访问”很有用,谢谢! (2认同)

小智 5

在 macOS 中只需打开 Macintosh HD

现在选择应用程序,然后选择Python文件夹(Python3.6、Python3.7无论您使用什么,只需选择此文件夹)

然后,双击安装证书命令。现在你的错误应该得到解决。


Joh*_*ohn 5

对我来说,解决方案非常简单:

  1. 将证书链下载为 PEM 文件。为此,我使用 Mozilla Firefox,查看了证书并单击链接“PEM(链)”,请参阅屏幕截图。

    在此输入图像描述

  2. requests 的文档之后,我添加了verify参数,即它看起来像是在步骤 1 中下载的文件requests.post(url, params, verify='/path/to/domain-chain.pem')在哪里。该函数也获得了该参数。使用会话时,也可以参见文档中的示例。domain-chain.pemgetverify

然后就成功了。