Python - [SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败:无法获取本地颁发者证书 (_ssl.c:1091)

Posted

技术标签:

【中文标题】Python - [SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败:无法获取本地颁发者证书 (_ssl.c:1091)【英文标题】:Python - [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1091) 【发布时间】:2021-11-25 21:12:54 【问题描述】:

我有一个 Amazon linux 2 虚拟机,我正在从这个虚拟机发出一个 python 请求。为了提出请求,我使用的是自签名证书。

我已将自签名证书文件内容附加到文件“/etc/pki/tls/certs/ca-bundle.crt”中。

CURL 命令工作正常,但是当使用 python 的 requests 方法发出请求时,它会抛出以下错误。

错误:(由 SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败:无法获取本地颁发者证书 (_ssl.c:1091)') 引起))

我尝试通过提供“MyAppcert.crt”和“ca_bundle.crt”文件的路径来对 Python 请求方法使用“验证”参数,但是这两种方法都失败了。

import requests
requests.get("https://<my-endpoint>:8888/", verify="/home/ec2-user/ssl_cert/MyAppcert.crt")

同样的用例在 Windows 服务器上运行良好。

任何帮助将不胜感激。

问候,

拉胡尔·库姆哈尔

【问题讨论】:

您是否安装了 certifi 模块?如果没有:做pip install certifi 不同的 TLS 堆栈验证证书的方式略有不同。确保自签名证书实际上启用了基本约束 CA:true(检查 openssl x509 -in file.pem -text @MarijnKneppers:certifi 对自签名证书没有帮助。它仅适用于公共 CA 颁发的证书。 【参考方案1】:

您需要在发送套接字时伪造 SSL。 在你的代码中试试这个:

    import ssl

# Ignore SSL certificate errors
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

or 

import ssl
ssl._create_default_https_context = ssl._create_unverified_context

这两个对我来说都很好,例如 - https://twitter.com/bro_dev_/status/1447598426120720384?s=20 我今天运行了这段代码并且它工作正常。 从: https://github.com/webprice/python-twitter-examples/blob/f8ad6f69f423afdcbd83d89cc7e17e2f61d92ed4/bs4_SSL

【讨论】:

【参考方案2】:

@SteffenUllrich 感谢您的回复。我使用“openssl x509 -in file.pem -text”验证了我的证书,发现缺少“keyUsage = Certificate Sign”。使用“keyUsage = Certificate Sign”创建新证书后,问题已解决。

【讨论】:

以上是关于Python - [SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败:无法获取本地颁发者证书 (_ssl.c:1091)的主要内容,如果未能解决你的问题,请参考以下文章

将SSL证书上载到IAM

在共享主机上自动生成和更新 SSL

python https协议和InsecurePlatformWarning问题

nginx端口重定向及反向代理

使用带有CODE JAVA的wsdl生成类,因为我跳过certificat

mysqli_real_connect() 获取 SSL3_GET_SERVER_CERTIFICATE:证书验证失败