Запрос Python, бросающий SSLError
Я работаю над простым script, который включает CAS, проверку безопасности jspring, перенаправление и т.д. Я бы хотел использовать запросы Python Kenneth Reitz, потому что это отличная работа! Тем не менее, 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:
Запросы могут проверять SSL-сертификаты для HTTPS-запросов, как и веб-браузер. Чтобы проверить SSL-сертификат хостов, вы можете использовать аргумент проверки:
>>> requests.get('https://kennethreitz.com', verify=True)
Если вы не хотите проверять свой сертификат SSL, сделайте verify=False
Ответ 3
Имя файла CA, которое вы можете использовать, можно передать через verify
:
cafile = 'cacert.pem' # http://curl.haxx.se/ca/cacert.pem
r = requests.get(url, verify=cafile)
Если вы используете verify=True
, то requests
использует свой собственный набор CA, у которого может не быть CA, который подписал ваш сертификат сервера.
Ответ 4
$ 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), версия запросов была 0.13.1. В версии 2.4.1 (2014-09) были введены дополнительные функции "безопасности" с использованием пакета certifi
, если он доступен.
Прямо сейчас (2016-09) основной версией является 2.11.1, которая хорошо работает без verify=False
. Нет необходимости использовать requests.get(url, verify=False)
, если установлено с requests[security]
дополнениями.
Ответ 5
Я столкнулся с той же проблемой, и сертификат ssl подтвердил ошибку при использовании aws boto3, просмотрев код 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
Ответ 6
Если у вас есть библиотека, которая полагается на requests
, и вы не можете изменить путь проверки (например, с помощью pyvmomi
), вам придется найти cacert.pem
в комплекте с запросами и добавить свой ЦС. Вот общий подход к поиску местоположения cacert.pem
:
окна
C:\>python -c "import requests; print requests.certs.where()"
c:\Python27\lib\site-packages\requests-2.8.1-py2.7.egg\requests\cacert.pem
Linux
# (py2.7.5,requests 2.7.0, verify not enforced)
[email protected]:~/# python -c "import requests; print requests.certs.where()"
/usr/lib/python2.7/dist-packages/certifi/cacert.pem
# (py2.7.10, verify enforced)
[email protected]:~/# python -c "import requests; print requests.certs.where()"
/usr/local/lib/python2.7/dist-packages/requests/cacert.pem
кстати. @request-devs, связывая ваши собственные cacerts с запросом, действительно, очень раздражает... особенно тот факт, что вы, похоже, не используете систему ca store, и это нигде не документировано.
Обновление
в ситуациях, когда вы используете библиотеку и не имеете контроля над местоположением ca-bundle, вы также можете явно указать местоположение ca-bundle в качестве своего часового пакета:
REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt python -c "import requests; requests.get('https://somesite.com';)"
Ответ 7
Я сталкиваюсь с той же проблемой, используя gspread, и эти команды работают для меня:
sudo pip uninstall -y certifi
sudo pip install certifi==2015.04.28
Ответ 8
Если вы хотите удалить предупреждения, используйте приведенный ниже код.
import urllib3
urllib3.disable_warnings()
и verify=False
с помощью метода request.get
или post
Ответ 9
Я нашел конкретный подход для решения подобной проблемы. Идея указывает на файл 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) сгенерировал сертификат.
EDIT: если вы не можете отредактировать код (потому что вы используете третье приложение), вы можете попробовать добавить сертификат pem
непосредственно в /usr/local/lib/python2.7/dist-packages/requests/cacert.pem
(например, скопировать его в конец файла).
Ответ 10
Если вы не беспокоитесь о сертификате, просто используйте verify=False
.
import requests
url = "Write your url here"
returnResponse = requests.get(url, verify=False)
Ответ 11
После нескольких часов отладки я мог заставить это работать только с помощью следующих пакетов:
requests[security]==2.7.0 # not 2.18.1
cryptography==1.9 # not 2.0
с помощью OpenSSL 1.0.2g 1 Mar 2016
Без этих пакетов verify=False
не работал.
Я надеюсь, что это поможет кому-то.
Ответ 12
Я столкнулся с той же проблемой. Оказывается, я не установил промежуточный сертификат на своем сервере (просто добавьте его в конец вашего сертификата, как показано ниже).
https://www.digicert.com/ssl-support/pem-ssl-creation.htm
Убедитесь, что у вас установлен пакет ca-сертификатов:
sudo apt-get install ca-certificates
Обновление времени также может решить следующее:
sudo apt-get install ntpdate
sudo ntpdate -u ntp.ubuntu.com
Если вы используете самозаверяющий сертификат, вам, вероятно, придется добавить его в свою систему вручную.
Ответ 13
Если вызовы запросов скрыты где-то глубоко в коде, и вы не хотите устанавливать сертификат сервера, то только для отладки только можно выполнить запросы 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!')
Никогда не используйте в производстве!
Ответ 14
Я боролся с этой проблемой за ЧАСЫ.
Я пытался обновлять запросы. Затем я обновил certifi. Я указал проверить certifi.where() (код делает это по умолчанию в любом случае). Ничего не получилось.
Наконец, я обновил мою версию python до python 2.7.11. Я был на Python 2.7.5, который имел некоторые несовместимости с тем, как проверяются сертификаты. Как только я обновил Python (и несколько других зависимостей), он начал работать.
Ответ 15
В модуле запросов в данный момент возникает проблема, вызывающая эту ошибку, представленную в 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'
Ответ 16
Как уже упоминалось @Rafael Almeida, проблема, с которой вы столкнулись, вызвана ненадежным сертификатом SSL. В моем случае сертификат SSL был не доверен моему серверу. Чтобы обойти это без ущерба для безопасности, я скачал сертификат и установил его на сервере (просто дважды щелкнув файл .crt, а затем установил сертификат...).
Ответ 17
Я полагаю, слишком поздно для вечеринки, но я хотел вставить исправление для таких странников, как я! Так что на 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
Ответ 18
Это похоже на ответ @rafael-almeida, но я хочу отметить, что по состоянию на запросы 2. 11+ нет 3 значений, которые может принять verify
, на самом деле 4:
True
: проверяет на соответствие запросам внутренних доверенных ЦС.
False
: полностью обходит проверку сертификата. (Не рекомендуется)
- Путь к файлу CA_BUNDLE. запросы будут использовать это для проверки сертификатов сервера.
- Путь к каталогу, содержащему открытые файлы сертификатов. запросы будут использовать это для проверки сертификатов сервера.
Остальная часть моего ответа о # 4, как использовать каталог, содержащий сертификаты для проверки:
Получите необходимые публичные сертификаты и поместите их в каталог.
Строго говоря, вы, вероятно, "должны" использовать внеполосный метод получения сертификатов, но вы также можете просто загрузить их с помощью любого браузера.
Если сервер использует цепочку сертификатов, обязательно получите каждый отдельный сертификат в цепочке.
Согласно документации по запросам, каталог, содержащий сертификаты, должен сначала обрабатываться утилитой rehash (openssl rehash
).
(Для этого требуется openssl 1.1. 1+, и не все реализации Windows openssl поддерживают перефразирование. Если openssl rehash
не будет работать для вас, вы можете попробовать запустить скрипт rehash ruby на https://github.com/ruby/openssl/blob/master/sample/c_rehash.rb, хотя я не пробовал этого.)
У меня были некоторые проблемы с получением запросов на распознавание моих сертификатов, но после того, как я использовал команду openssl x509 -outform PEM
для преобразования сертификатов в формат Base64 .pem
, все работало отлично.
Вы также можете просто сделать перефразировку:
try:
# As long as the certificates in the certs directory are in the OS 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")
Ответ 19
Невозможно добавить опции, если запросы вызывают из другого пакета. В этом случае добавление сертификатов в пакет cacert является прямым путем, например. Мне пришлось добавить "StartCom Class 1 Primary Intermediate Server CA", для которого я загрузил корневой сертификат в StartComClass1.pem. поскольку мой virtualenv называется 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
одного из них может быть достаточно, я не проверял
Ответ 20
У меня была аналогичная или одна и та же проблема проверки сертификатов. Я читал, что версии 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())
Ответ 21
Мне пришлось обновить Python 3.4.0 до 3.4.6
pyenv virtualenv 3.4.6 myvenv
pyenv activate myvenv
pip install -r requirements.txt
Ответ 22
В моем случае причина была довольно тривиальной.
Я знал, что проверка SSL работала несколько дней назад и фактически работала на другом компьютере.
Следующим моим шагом было сравнение содержимого и размера сертификата между машиной, на которой работала проверка, и той, на которой ее не было.
Это быстро привело меня к определению, что сертификат на "неправильно" работающей машине не был хорош, и как только я заменил его на "хороший" сертификат, все было хорошо.