简体   繁体   English

Python 请求 SSL 错误 - 证书验证失败

[英]Python requests SSL error - certificate verify failed

This code这段代码

import requests
requests.get("https://hcaidcs.phe.org.uk/WebPages/GeneralHomePage.aspx")

is giving me this error给我这个错误

[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)

I know practically nothing about SSL, but I've tried downloading the site's certificate and pointing to that file using the verify option, but it hasn't worked.我对 SSL 几乎一无所知,但我尝试下载该站点的证书并使用verify选项指向该文件,但没有成功。 Am I missing something?我错过了什么吗?

As already pointed out in a comment: the site has a bad SSL implementation as can be seen from the SSLLabs report .正如评论中已经指出的那样:从SSLLabs 报告中可以看出,该站点的 SSL 实施很糟糕。 The main part of this report regarding your problem is:这份报告中关于您的问题的主要部分是:

This server's certificate chain is incomplete.此服务器的证书链不完整。 Grade capped to B.等级上限为 B。

This means that the server is not sending the full certificate chain as is needed to verify the certificate.这意味着服务器没有发送验证证书所需的完整证书链。 This means you need to add the missing certificates yourself when validating.这意味着您需要在验证时自己添加缺少的证书。 For this you need to include the PEM for the missing chain certificate C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 High Assurance Server CA and also for the root CA C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA info a file my_trust_store.pem and then you can call:为此,您需要为缺少的链证书C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 High Assurance Server CA以及根 CA C=US, O=包含 PEM DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA info a file my_trust_store.pem然后您可以调用:

requests.get("https://...", verify='my_trust_store.pem')

... but I've tried downloading the site's certificate and pointing to that file using the verify option ...但我尝试下载该站点的证书并使用验证选项指向该文件

This will not work with normal leaf certificates.这不适用于普通的叶子证书。 Since the SSL stack of Python is based on OpenSSL and OpenSSL expects only trusted certificate authorities in the trust store (ie given with verify ) and a server certificate is not CA certificate it will not help to add it to the trust store.由于 Python 的 SSL 堆栈基于 OpenSSL,并且 OpenSSL 只希望信任库中的受信任证书颁发机构(即使用verify给出)并且服务器证书不是 CA 证书,因此将其添加到信任库无济于事。

cat institution-certificate.pem >> venv/lib/python3.9/site-packages/certifi/cacert.pem

如果您的网络需要 CA,这应该可以解决问题

using the certifi doesn't seem to be implied, so i'll show you what made my solution:使用 certifi 似乎并不暗示,所以我会告诉你是什么让我的解决方案:

import urllib, urllib2, ssl
import certifi

request = urllib2.Request(url=url)
kw = dict()
if url.startswith('https://'):
    certifi_context = ssl.create_default_context(cafile=certifi.where())
    kw.update(context=certifi_context)
urllib2.urlopen(request, **kw)

i found this solution and more on RealPython, here 我在 RealPython 上找到了这个解决方案和更多信息,在这里

If you can avoid the certificate verification (not secure), set PYTHONHTTPSVERIFY environment variable to 0:如果可以避免证书验证(不安全),请将 PYTHONHTTPSVERIFY 环境变量设置为 0:

export PYTHONHTTPSVERIFY=0

This will skip the certificate verification.这将跳过证书验证。

import requests
html = requests.get("https://hcaidcs.phe.org.uk/WebPages/GeneralHomePage.aspx",verify=False).text

You should write it like this, and I've verified it你应该这样写,我已经验证过了

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM