我正在编写一个简单的脚本,涉及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

当前回答

如果要删除警告,请使用下面的代码。

import urllib3

urllib3.disable_warnings()

and verify=False与请求。Get或post方法

其他回答

我认为你有几种方法可以解决这个问题。我提到了以下5种方法:

你可以为每个请求定义上下文,并在每个请求上传递上下文,如下所示:

import certifi
import ssl
import urllib
context = ssl.create_default_context(cafile=certifi.where())
result = urllib.request.urlopen('https://www.example.com', context=context)

或在环境中设置证书文件。

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')

创建默认的https上下文方法:

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')

如果您使用Linux机器,生成新的证书并导出指向证书目录的环境变量,则可以修复该问题。

$ sudo update-ca-certificates --fresh
$ export SSL_CERT_DIR=/etc/ssl/certs

或如果您使用Mac机器,生成新的证书

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

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

在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(例如将其复制到文件的末尾)。

我在使用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

我遇到了类似或相同的认证验证问题。我读到过小于1.0.2的OpenSSL版本,请求所依赖的版本有时会在验证强证书时遇到麻烦(见这里)。CentOS 7似乎使用了1.0.1e,这似乎有问题。

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

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

我找到了一个解决问题的答案:

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()))

但我不知道它是干什么用的。