Python 请求抛出 SSLError

2024-12-05 08:37:00
admin
原创
146
摘要:问题描述:我正在编写一个涉及 CAS、jspring 安全检查、重定向等的简单脚本。我想使用 Kenneth Reitz 的 python 请求,因为它是一项很棒的工作!但是,CAS 需要通过 SSL 进行验证,所以我必须先完成该步骤。我不知道 Python 请求想要什么?这个 SSL 证书应该放在哪里?Tr...

问题描述:

我正在编写一个涉及 CAS、jspring 安全检查、重定向等的简单脚本。我想使用 Kenneth Reitz 的 python 请求,因为它是一项很棒的工作!但是,CAS 需要通过 SSL 进行验证,所以我必须先完成该步骤。我不知道 Python 请求想要什么?这个 SSL 证书应该放在哪里?

Traceback (most recent call last):
  File "./test.py", line 24, in <module>
  response = requests.get(url1, headers=headers)
  File "build/bdist.linux-x86_64/egg/requests/api.py", line 52, in get
  File "build/bdist.linux-x86_64/egg/requests/api.py", line 40, in request
  File "build/bdist.linux-x86_64/egg/requests/sessions.py", line 209, in request 
  File "build/bdist.linux-x86_64/egg/requests/models.py", line 624, in send
  File "build/bdist.linux-x86_64/egg/requests/models.py", line 300, in _build_response
  File "build/bdist.linux-x86_64/egg/requests/models.py", line 611, in send
requests.exceptions.SSLError: [Errno 1] _ssl.c:503: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

解决方案 1:

您遇到的问题是由不受信任的 SSL 证书引起的。

就像 @dirk 在之前的评论中提到的那样,最快的解决方法是设置verify=False

requests.get('https://example.com', verify=False)

请注意,这将导致证书无法验证。这将使您的应用程序面临安全风险,例如中间人攻击。

当然,要运用判断力。正如评论中提到的,这对于快速/一次性应用程序/脚本来说可能是可以接受的,但实际上不应该用于生产软件

如果在您的特定情况下无法接受跳过证书检查,请考虑以下选项,最好的选择是将verify参数设置为证书文件的路径字符串.pem(您应该通过某种安全方式获取)。

因此,从 2.0 版开始,该verify参数接受以下值及其各自的语义:

  • True:导致证书根据库自己的受信任证书颁发机构进行验证(注意:您可以通过 Certifi 库查看请求使用哪些根证书,该库是从请求中提取的 RC 信任数据库:Certifi - 人类的信任数据库)。

  • False:完全绕过证书验证。

  • 用于验证证书的请求的 CA_BUNDLE 文件的路径。

来源:请求 - SSL 证书验证

还请查看cert同一链接上的参数。

解决方案 2:

来自有关 SSL 验证的请求文档:

Requests 可以验证 HTTPS 请求的 SSL 证书,就像 Web 浏览器一样。要检查主机的 SSL 证书,可以使用 verify 参数:

>>> requests.get('https://kennethreitz.com', verify=True)

如果你不想验证你的 SSL 证书,请verify=False

解决方案 3:

我在使用 aws boto3 时遇到了同样的问题和 ssl 证书验证失败问题,通过查看 boto3 代码,我发现REQUESTS_CA_BUNDLE没有设置,因此我通过手动设置解决了这两个问题:

from boto3.session import Session
import os

# debian
os.environ['REQUESTS_CA_BUNDLE'] = os.path.join(
    '/etc/ssl/certs/',
    'ca-certificates.crt')
# centos
#   'ca-bundle.crt')

对于 aws-cli,我猜测设置 REQUESTS_CA_BUNDLE~/.bashrc将修复此问题(未经测试,因为我的 aws-cli 没有它也可以工作)。

REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt # ca-bundle.crt
export REQUESTS_CA_BUNDLE

解决方案 4:

您可以通过以下方式传递要使用的 CA 文件的名称verify

cafile = 'cacert.pem' # http://curl.haxx.se/ca/cacert.pem
r = requests.get(url, verify=cafile)

如果您使用,verify=Truerequests使用其自己的 CA 集,该集可能没有签署您的服务器证书的 CA。

解决方案 5:

$ pip install -U requests[security]

  • 在 Python 2.7.6 @ Ubuntu 14.04.4 LTS 上测试

  • 在 Python 2.7.5 @ MacOSX 10.9.5 (Mavericks) 上测试

当这个问题被提出时(2012-05),Requests 版本是 0.13.1。在版本2.4.1(2014-09)中,引入了“安全”附加功能,certifi如果可用则使用包。

目前 (2016-09) 主要版本是 2.11.1,没有 也能正常工作 如果安装了附加程序,则verify=False无需使用。requests.get(url, verify=False)`requests[security]`

解决方案 6:

如果您有一个依赖的库requests,并且您无法修改验证路径(例如pyvmomi),那么您必须找到cacert.pem捆绑的请求并将您的 CA 附加在那里。以下是查找位置的通用方法cacert.pem

视窗

C:>python -c "import requests; print requests.certs.where()"
c:Python27libsite-packages
equests-2.8.1-py2.7.egg
equestscacert.pem

Linux的

#  (py2.7.5,requests 2.7.0, verify not enforced)
root@host:~/# python -c "import requests; print requests.certs.where()"
/usr/lib/python2.7/dist-packages/certifi/cacert.pem

#  (py2.7.10, verify enforced)
root@host:~/# python -c "import requests; print requests.certs.where()"
/usr/local/lib/python2.7/dist-packages/requests/cacert.pem

顺便说一句。@requests-devs,将您自己的 cacerts 与请求捆绑在一起确实非常烦人......尤其是您似乎没有首先使用系统 ca 存储,并且这在任何地方都没有记录。

更新

在您使用库并且无法控制 ca-bundle 位置的情况下,您还可以明确将 ca-bundle 位置设置为主机范围的 ca-bundle:

REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt python -c "import requests; requests.get('https://somesite.com')";

解决方案 7:

正如其他人指出的那样,此问题“是由不受信任的 SSL 证书引起的”。我的答案基于评分最高的答案和此答案。

您可以使用以下方法测试证书curl

curl -vvI https://example.com

如果返回错误,您有 3 个选择:

  1. 为了快速解决问题,您可以不验证证书:

requests.get('https://example.com', verify=False)
  1. 将路径传递给具有受信任 CA 的证书的 CA_BUNDLE 文件或目录:

requests.get('https://example.com', verify='/path/to/certfile')
  1. 如果您有权访问,请修复 Web 服务器证书。

我的问题是因为我只使用了我的网站的证书,而不是中间(又名链)证书。

如果您使用 Let's Encrypt,则应该使用fullchain.pem文件,而不是cert.pem

解决方案 8:

如果您想删除警告,请使用以下代码。

import urllib3

urllib3.disable_warnings()

以及或方法verify=Falserequest.get()`post()`

import requests

requests.get(url, verify=False)

解决方案 9:

我在使用 gspread 时遇到同样的问题,这些命令对我有用:

sudo pip uninstall -y certifi
sudo pip install certifi==2015.04.28

解决方案 10:

我找到了一种解决类似问题的具体方法。这个想法是指向存储在系统中并由另一个基于 SSL 的应用程序使用的cacert 文件。

在 Debian 中(我不确定其他发行版是否相同),证书文件(.pem)存储在/etc/ssl/certs/因此,这是对我有用的代码:

import requests
verify='/etc/ssl/certs/cacert.org.pem'
response = requests.get('https://lists.cacert.org', verify=verify)

为了猜测pem选择哪个文件,我浏览了 URL 并检查哪个证书颁发机构 (CA) 生成了该证书。

编辑:如果您无法编辑代码(因为您正在运行第三个应用程序),您可以尝试将证书pem直接添加到其中/usr/local/lib/python2.7/dist-packages/requests/cacert.pem(例如将其复制到文件末尾)。

解决方案 11:

如果您不关心证书,只需使用verify=False

import requests

url = "Write your url here"

returnResponse = requests.get(url, verify=False)

解决方案 12:

经过几个小时的调试,我只能使用以下软件包才能使其工作:

requests[security]==2.7.0  # not 2.18.1
cryptography==1.9  # not 2.0

使用OpenSSL 1.0.2g 1 Mar 2016

如果没有这些包verify=False就无法工作。

我希望这对某人有帮助。

解决方案 13:

我遇到了同样的问题。原来我没有在服务器上安装中间证书(只需将其附加到证书底部,如下所示)。

https://www.digicert.com/ssl-support/pem-ssl-creation.htm

确保您已经安装了 ca-certificates 包:

sudo apt-get install ca-certificates

更新时间也许可以解决这个问题:

sudo apt-get install ntpdate
sudo ntpdate -u ntp.ubuntu.com

如果您使用自签名证书,则可能必须手动将其添加到系统中。

解决方案 14:

如果请求调用埋在代码深处的某个地方,并且您不想安装服务器证书,那么,仅出于调试目的,可以使用 monkeypatch 请求:

import requests.api
import warnings


def requestspatch(method, url, **kwargs):
    kwargs['verify'] = False
    return _origcall(method, url, **kwargs)

_origcall = requests.api.request
requests.api.request = requestspatch
warnings.warn('Patched requests: SSL verification disabled!')

切勿在生产中使用!

解决方案 15:

我想这已经太迟了,但我想把这个修复贴出来给和我一样的迷路者!所以下面的方法在 Python 3.7.x 上对我有用

在终端中输入以下内容

pip install --upgrade certifi      # hold your breath..

尝试再次运行脚本/请求,看看它是否有效(我确定它还没有修复!)。如果它不起作用,请尝试直接在终端中运行以下命令

open /Applications/Python 3.6/Install Certificates.command  # please replace 3.6 here with your suitable python version

解决方案 16:

这与@rafael-almeida的回答类似,但我想指出的是,从请求 2.11+ 开始,verify可以采用的值不再是 3 个,实际上有 4 个:

  • True:根据请求的内部可信 CA 进行验证。

  • False:完全绕过证书验证。(不推荐)

  • CA_BUNDLE 文件的路径。请求将使用它来验证服务器的证书。

  • 包含公共证书文件的目录的路径。请求将使用它来验证服务器的证书。

我的答案的其余部分是关于#4,如何使用包含证书的目录进行验证:

获取所需的公共证书并将其放在目录中。

严格来说,您可能“应该”使用带外方法来获取证书,但您也可以使用任何浏览器下载它们。

如果服务器使用证书链,请确保获取链中的每个证书。

根据请求文档,必须首先使用“rehash”实用程序 ( openssl rehash) 处理包含证书的目录。

(这需要 openssl 1.1.1+,并且并非所有 Windows openssl 实现都支持 rehash。如果openssl rehash不适合您,您可以尝试运行https://github.com/ruby/openssl/blob/master/sample/c_rehash.rb上的 rehash ruby​​ 脚本,尽管我还没有尝试过。)

我在获取识别证书的请求时遇到了一些麻烦,但在我使用命令openssl x509 -outform PEM将证书转换为 Base64.pem格式后,一切都顺利了。

你也可以进行惰性重新散列:

try:
    # As long as the certificates in the certs directory are in the OS's certificate store, `verify=True` is fine.
    return requests.get(url, auth=auth, verify=True)
except requests.exceptions.SSLError:
    subprocess.run(f"openssl rehash -compat -v my_certs_dir", shell=True, check=True)
    return requests.get(url, auth=auth, verify="my_certs_dir")

解决方案 17:

我花了几个小时来解决这个问题。

我尝试更新请求。然后我更新了 certifi。我将 verify 指向 certifi.where()(代码默认会这样做)。但什么都没起作用。

最后,我将 Python 版本更新为 Python 2.7.11。我之前使用的是 Python 2.7.5,它与证书验证方式存在一些不兼容。更新 Python(以及一些其他依赖项)后,它开始正常工作。

解决方案 18:

一些服务器没有 Letsencrypt 的可信根证书。

例如,假设下面的 url 指向的服务器受到 Letsencrypt SSL 保护。

requests.post(url, json=data)

此请求可能失败,并出现 [SSL:CERTIFICATE_VERIFY_FAILED],因为请求服务器没有 Letsencrypt 的根证书。

发生这种情况时,请从下面的链接下载活动的自签名“pem”证书。

https://letsencrypt.org/certificates/。(截至撰写本文时,ISRG Root X1 处于活动状态)

现在,在验证参数中使用它,如下所示。

requests.post(url, json=data, verify='path-to/isrgrootx1.pem')

解决方案 19:

我认为您有几种方法可以解决此问题。我在下面提到了 5 种方法:

  1. 您可以为每个请求定义上下文,并在每个请求上传递上下文以供使用,如下所示:

import certifi
import ssl
import urllib
context = ssl.create_default_context(cafile=certifi.where())
result = urllib.request.urlopen('https://www.example.com', context=context)
  1. 或 在 中设置证书文件environment

import os
import certifi
import urllib
os.environ["REQUESTS_CA_BUNDLE"] = certifi.where()
os.environ["SSL_CERT_FILE"] = certifi.where()
result = urllib.request.urlopen('https://www.example.com')

  1. 或更换create default https context方法:

import certifi
import ssl
ssl._create_default_https_context = lambda: ssl.create_default_context(cafile=certifi.where())
result = urllib.request.urlopen('https://www.example.com')
  1. 或者如果您使用Linux机器,生成新的证书并导出指向证书目录的环境变量即可解决问题。

$ sudo update-ca-certificates --fresh
$ export SSL_CERT_DIR=/etc/ssl/certs
  1. 或者如果你使用Mac机器,生成新证书

$ cd "/Applications/$(python3 --version | awk '{print $2}'| awk  -F. '{print "Python " $1"."$2}')"
$ sudo "./Install Certificates.command"

解决方案 20:

对我来说,这里的一切都失败了。我的公司使用 Z-Scaler,最近激活了一些额外的保护,导致 Python 包plantweb失败并出现以下错误:

SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate

问题是 Z-Scaler 使用它自己的证书,所以我需要从 IT 部门获取该文件并告诉 python 使用它。

export REQUESTS_CA_BUNDLE="/path/to/zscaler.crt"
plantweb --format png some_file.puml

然而,这又带来了另一个问题:我开始运行的一些其他代码由于需要使用来自 pythoncertifi包的标准证书而出现相同的 SSL 错误。

对我来说,最终的解决方案是将普通证书和 Z-Scaler 证书合并为一个证书,并告诉 python 使用该证书:

pip3 install certifi
normal_python_cert="$(python3 -m certifi)"
cat $normal_python_cert /path/to/zscaler.crt > combined.crt
export REQUESTS_CA_BUNDLE=/path/to/combined.crt
plantweb --format png some_file.puml

超级有用的参考:
https ://help.zscaler.com/zia/adding-custom-certificate-application-specific-trust-store#python

解决方案 21:

目前,请求模块中存在一个问题,导致此错误,存在于 v2.6.2 至 v2.12.4(ATOW)中:https ://github.com/kennethreitz/requests/issues/2573

解决此问题的方法是添加以下行:requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS'

解决方案 22:

正如@Rafael Almeida 所说,您遇到的问题是由不受信任的 SSL 证书引起的。就我而言,我的服务器不信任 SSL 证书。为了在不损害安全性的情况下解决这个问题,我下载了证书,并将其安装在服务器上(只需双击 .crt 文件,然后安装证书...)。

解决方案 23:

就我而言,原因相当简单。

几天前我就已经知道 SSL 验证已经起作用了,而且实际上是在另一台机器上运行的。

我的下一步是比较正在进行验证的机器和未进行验证的机器之间的证书内容和大小。

这很快让我确定“错误”工作的机器上的证书不好,一旦我用“好”的证书替换它,一切都正常了。

解决方案 24:

如果从另一个包调用请求,则无法添加选项。在这种情况下,将证书添加到 cacert 包是直接路径,例如,我必须添加“StartCom Class 1 Primary Intermediate Server CA”,为此我将根证书下载到 StartComClass1.pem 中。鉴于我的虚拟环境名为 caldav,我使用以下命令添加了证书:

cat StartComClass1.pem >> .virtualenvs/caldav/lib/python2.7/site-packages/pip/_vendor/requests/cacert.pem
cat temp/StartComClass1.pem >> .virtualenvs/caldav/lib/python2.7/site-packages/requests/cacert.pem

其中一个可能就足够了,我没有检查

解决方案 25:

我遇到了类似或相同的证书验证问题。我读到,请求所依赖的 OpenSSL 版本低于 1.0.2 时,有时无法验证强证书(请参阅此处)。CentOS 7 似乎使用 1.0.1e,这似乎存在问题。

我不确定如何在 CentOS 上解决这个问题,所以我决定允许较弱的 1024 位 CA 证书。

import certifi # This should be already installed as a dependency of 'requests'
requests.get("https://example.com", verify=certifi.old_where())

解决方案 26:

我必须从 Python 3.4.0 升级到 3.4.6

pyenv virtualenv 3.4.6 myvenv
pyenv activate myvenv
pip install -r requirements.txt

解决方案 27:

我找到了这个答案并修复了它:

import ssl
import certifi
import urllib.request

url = "https://www.google.com/"
html = urllib.request.urlopen(url, context=ssl.create_default_context(cafile=certifi.where()))

但我不知道它是做什么的。

解决方案 28:

当它说verify需要“证书路径”时,我将其指向颁发者证书,以便可以使用它来验证 url 的证书。curl并且wget对该证书没有异议。但不是 python 请求。

我必须创建一个证书链,其中包含从端(叶?)到根的所有证书,以便 python 请求能够正常处理。而且该链也可以自然地与 cURL 和 Wget 配合使用。

希望它能帮助到一些人并且节省几个小时。

解决方案 29:

这只是您可以尝试解决问题的另一种方法。

如果您输入“www.example.com”,请求会向您发出警告。如果您输入“https://www.example.com”,则会收到此错误。因此,如果您不需要 https,您可以通过将“https”更改为“http”来避免错误。例如“http://www.example.com

警告:不使用 HTTPS 通常不是一个好主意。请参阅为什么一切都使用 HTTPS? 为什么 HTTPS 很重要

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用