it-roy-ru.com

urllib и ошибка "SSL: CERTIFICATE_VERIFY_FAILED"

Я получаю следующую ошибку:

Exception in thread Thread-3:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 810, in        __bootstrap_inner
self.run()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 763, in  run
self.__target(*self.__args, **self.__kwargs)
File "/Users/Matthew/Desktop/Skypebot 2.0/bot.py", line 271, in process
info = urllib2.urlopen(req).read()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 431, in open
response = self._open(req, data)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 449, in _open
'_open', req)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 409, in _call_chain
result = func(*args)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1240, in https_open
context=self._context)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1197, in do_open
raise URLError(err)
URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)>

Это код, который вызывает эту ошибку:

if input.startswith("!web"):
    input = input.replace("!web ", "")      
    url = "https://domainsearch.p.mashape.com/index.php?name=" + input
    req = urllib2.Request(url, headers={ 'X-Mashape-Key': 'XXXXXXXXXXXXXXXXXXXX' })
    info = urllib2.urlopen(req).read()
    Message.Chat.SendMessage ("" + info)

API, который я использую, требует от меня использования HTTPS. Как я могу сделать это в обход проверки?

192
user3724476

Если вы просто хотите обойти проверку, вы можете создать новый SSLContext . По умолчанию вновь созданные контексты используют CERT_NONE .

Будьте осторожны с этим, как указано в разделе 17.3.7.2.1

При непосредственном вызове конструктора SSLContext по умолчанию используется CERT_NONE. Поскольку он не аутентифицирует другого партнера, он может быть небезопасным, особенно в режиме клиента, где большую часть времени вы хотели бы обеспечить аутентичность сервера, с которым вы разговариваете. Поэтому, когда в режиме клиента, настоятельно рекомендуется использовать CERT_REQUIRED. 

Но если вы просто хотите, чтобы это работало сейчас, по какой-то другой причине, вы можете сделать следующее, вам также нужно будет import ssl:

input = input.replace("!web ", "")      
url = "https://domainsearch.p.mashape.com/index.php?name=" + input
req = urllib2.Request(url, headers={ 'X-Mashape-Key': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' })
gcontext = ssl.SSLContext()  # Only for gangstars
info = urllib2.urlopen(req, context=gcontext).read()
Message.Chat.SendMessage ("" + info)

Это должно обойти вашу проблему, но вы на самом деле не решаете ни одну из проблем, но вы не увидите [SSL: CERTIFICATE_VERIFY_FAILED], потому что вы сейчас не проверяете сертификат!

В дополнение к вышесказанному, если вы хотите узнать больше о том, почему вы видите эти проблемы, вам нужно взглянуть на PEP 476 .

В этом PEP предлагается включить проверку подписей сертификатов X509, а также проверку имени хоста для клиентов Python HTTP по умолчанию при условии отказа для каждого вызова. Это изменение будет применено к Python 2.7, Python 3.4 и Python 3.5. 

Есть рекомендованный отказ, который не отличается от моего совета выше:

import ssl

# This restores the same behavior as before.
context = ssl._create_unverified_context()
urllib.urlopen("https://no-valid-cert", context=context)

Он также имеет параметр крайне обескураженный через monkeypatching , который вы не часто видите в python:

import ssl

ssl._create_default_https_context = ssl._create_unverified_context

Который переопределяет функцию по умолчанию для создания контекста с помощью функции для создания непроверенного контекста.

Обратите внимание на это, как указано в PEP:

Это руководство предназначено, прежде всего, для системных администраторов, которые хотят внедрить более новые версии Python, которые реализуют этот PEP в устаревших средах, которые еще не поддерживают проверку сертификатов для соединений HTTPS. Например, администратор может отказаться, добавив указанный выше обезьян-патч к sitecustomize.py в их стандартной операционной среде для Python. Приложениям и библиотекам НЕ СЛЕДУЕТ делать этот процесс широким (за исключением, возможно, в ответ на настройки конфигурации, контролируемые системным администратором). 

Если вы хотите прочитать статью о том, почему не проверка сертификатов плоха в программном обеспечении вы можете найти ее здесь !

217
Noelkd

Это не решение вашей конкретной проблемы, но я привожу это здесь, потому что этот поток является лучшим результатом Google для "SSL: CERTIFICATE_VERIFY_FAILED", и это привело меня к безумной погоне за погоней.

Если вы установили Python 3.6 в OSX и получаете ошибку «SSL: CERTIFICATE_VERIFY_FAILED» при попытке подключиться к сайту https: //, возможно, это связано с тем, что Python 3.6 в OSX вообще не имеет сертификатов и не может проверить любой SSL соединения. Это изменение для 3.6 в OSX, и оно требует шага после установки, который устанавливает пакет сертификатов certifi. Это задокументировано в ReadMe, который вы должны найти по адресу /Applications/Python\ 3.6/ReadMe.rtf

ReadMe предложит вам запустить этот скрипт после установки, который просто устанавливает certifi: /Applications/Python\ 3.6/Install\ Certificates.command

Примечания к выпуску содержат дополнительную информацию: https://www.python.org/downloads/release/python-360/

246
Craig Glennie

Чтобы расширить ответ Крейга Гленни (извините, недостаточно репутации, чтобы комментировать):

в Python 3.6.1 на MacOs Sierra

Ввод этого в терминале bash решил проблему:

pip install certifi
/Applications/Python\ 3.6/Install\ Certificates.command
47
jnPy

В Windows Python не смотрит на системный сертификат, он использует свой собственный, расположенный в ?\lib\site-packages\certifi\cacert.pem.

Решение вашей проблемы: 

  1. скачать сертификат валидации домена в виде * .crt или * pem файла
  2. откройте файл в редакторе и скопируйте его содержимое в буфер обмена
  3. найдите свое местоположение cacert.pem: from requests.utils import DEFAULT_CA_BUNDLE_PATH; print(DEFAULT_CA_BUNDLE_PATH)
  4. отредактируйте файл cacert.pem и вставьте сертификат проверки домена в конец файла.
  5. Сохраните файл и наслаждайтесь запросами!
25
Bruno Gabuzomeu

Мое решение для Mac OS X:

1) Обновление до Python 3.6.5 с использованием собственного установщика Python, загруженного с официального сайта языка Python https://www.python.org/downloads/

Я обнаружил, что этот установщик позаботится об обновлении ссылок и символических ссылок для нового Python намного лучше, чем homebrew. 

2) Установите новый сертификат, используя «./Install Certificates.command», который находится в обновленном каталоге Python 3.6. 

> cd "/Applications/Python 3.6/"
> Sudo "./Install Certificates.command"
22
Claude COULOMBE

Вы можете попробовать добавить это к переменным вашей среды:

PYTHONHTTPSVERIFY=0 

Обратите внимание, что это отключит все HTTP проверку, так что это немного похоже на кувалду, однако, если проверка не требуется, это может быть эффективным решением.

22
Chris Halcrow

У меня была похожая проблема, хотя я использовал urllib.request.urlopen в Python 3.4, 3.5 и 3.6. (Это часть Python 3, эквивалентная urllib2, согласно примечанию в начале страницы документации Python 2 urllib2 .)

Мое решение состояло в том, чтобы pip install certifi установить certifi , который имеет:

... тщательно отобранная коллекция корневых сертификатов для проверки надежности сертификатов SSL при проверке подлинности хостов TLS.

Затем в моем коде, где я ранее только что был:

import urllib.request as urlrq
resp = urlrq.urlopen('https://foo.com/bar/baz.html')

Я изменил это, чтобы:

import urllib.request as urlrq
import certifi
resp = urlrq.urlopen('https://foo.com/bar/baz.html', cafile=certifi.where())

Если я правильно прочитал urllib2.urlopen документацию , у нее также есть аргумент cafile. Таким образом, urllib2.urlopen([...], certifi.where()) может работать и для Python 2.7.

12
hBy2Py
import requests
requests.packages.urllib3.disable_warnings()

import ssl

try:
    _create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
    # Legacy Python that doesn't verify HTTPS certificates by default
    pass
else:
    # Handle target environment that doesn't support HTTPS verification
    ssl._create_default_https_context = _create_unverified_https_context

Взято отсюда https://Gist.github.com/michaelrice/a6794a017e349fc65d01

11
Prostak

Как я уже писал в комментарии, эта проблема, вероятно, связана с этим SO ответом

Вкратце: существует несколько способов проверки сертификата. Проверка, используемая OpenSSL, несовместима с доверенными корневыми сертификатами, имеющимися в вашей системе. OpenSSL используется Python.

Вы можете попытаться получить отсутствующий сертификат для публичного первичного центра сертификации Verisign Class 3 , а затем использовать опцию cafile в соответствии с документацией Python :

urllib2.urlopen(req, cafile="verisign.pem")
9
Steffen Ullrich

Для Python 3.4+ on Centos 6/7, Fedora , просто установите доверенный CA следующим образом:

  1. Скопируйте CA.crt в /etc/pki/ca-trust/source/anchors/
  2. update-ca-trust force-enable
  3. update-ca-trust extract
4
Cherif KAOUA

Мне нужно добавить еще один ответ, потому что, как и Крейг Гленни, я продолжал погоню за гусиной кожей из-за множества постов, посвященных этой проблеме в Интернете.

Я использую MacPorts, и то, что я изначально думал, что это проблема Python, на самом деле было проблемой MacPorts: он не устанавливает корневой сертификат при установке openssl. Решение состоит в том, чтобы port install curl-ca-bundle, как упомянуто в это сообщение в блоге .

3
corwin.amber

Я опускаю голову в полус стыде, поскольку у меня была та же проблема, за исключением того, что в моем случае URL, который я нажимал, был действительным, сертификат был действительным. Недействительным было мое подключение к сети. Мне не удалось добавить детали прокси в браузер (в данном случае IE). Это остановило процесс проверки правильности.
Добавил в прокси подробности и мой питон был тогда очень счастлив.

2
Ads

Я удивлен, что все эти инструкции не решили мою проблему. Тем не менее, диагностика правильная (кстати, я использую Mac и Python3.6.1). Итак, подведем итог правильной части:

  • На Mac Apple выпускает OpenSSL
  • Python теперь использует собственный набор корневых сертификатов CA
  • Двоичная установка Python предоставила скрипт для установки корневого сертификата CA, необходимого Python ("/ Applications/Python 3.6/Install Certificates.command")
  • Подробнее читайте в "/ Applications/Python 3.6/ReadMe.rtf"

Для меня скрипт не работает, и все эти установки certifi и openssl тоже не удалось исправить. Может быть, потому что у меня есть несколько установок Python 2 и 3, а также много virtualenv. В конце мне нужно починить вручную.

pip install certifi   # for your virtualenv
mkdir -p /Library/Frameworks/Python.framework/Versions/3.6/etc/openssl
cp -a <your virtualenv>/site-package/certifi/cacert.pem \
  /Library/Frameworks/Python.framework/Versions/3.6/etc/openssl/cert.pem

Если это все еще не удается. Затем переустановите OpenSSL.

port install openssl
2
berniey

Как и вы, я использую python 2.7 на моем старом iMac (OS X 10.6.8), я тоже столкнулся с проблемой, используя urllib2.urlopen: 

urlopen error [SSL: CERTIFICATE_VERIFY_FAILED]

Мои программы работали нормально, без проблем с сертификатами SSL, и неожиданно (после загрузки программ) они вылетали с этой ошибкой SSL.

Проблема заключалась в используемой версии python:

  1. Нет проблем с https://www.python.org/downloads и python-2.7.9-macosx10.6.pkg

  2. проблема с установкой инструментом Homebrew : "brew install python", версия находится в/usr/local/bin.

Глава под названием Certificate verification and OpenSSL [CHANGED for Python 2.7.9] в /Applications/Python 2.7/ReadMe.rtf объясняет проблему многими деталями.

Итак, проверьте, скачайте и вставьте в ваш PATH нужную версию python.

2
Thierry Maillard

Пытаться

pip install --trusted-Host pypi.python.org имя_пакета

Это сработало для меня. 

1
user3603105

Взгляни на

/ Приложения/Python 3.6/Установить Certificates.command

Вы также можете перейти к разделу «Приложения» и нажать «Сертификаты»

1
Danielle Cohen

В Python 2.7.12 (по умолчанию, 29 июля 2016, 15:26:22) исправлена ​​упомянутая проблема. Эта информация может помочь кому-то еще.

1
caot

Для тех, кто использует mechanize, кто сталкивается с этим вопросом, вот как вы можете применить ту же технику к механизированному экземпляру Browser:

br = mechanize.Browser()
context = ssl._create_unverified_context()
br.set_ca_data(context=context)
0
Kirkman14

Если вы используете vCenter 6, вам следует вместо этого добавить сертификат центра сертификации vmware вашего vCenter в список доверенных ЦС вашей ОС. Для загрузки вашего сертификата сделайте следующее

  1. Откройте ваш веб-браузер.
  2. Перейдите к https: //
  3. В правом нижнем углу нажмите ссылку Загрузить доверенный корневой центр сертификации. 

На федоре 

  1. разархивируйте и измените расширение с .0 на .cer 
  2. Скопируйте его в/etc/pki/ca-trust/source/anchors /
  3. выполните команду update-ca-trust.

Ссылки:

  1. https://virtualizationreview.com/articles/2015/04/02/install-root-self-signed-certificate-vcenter-6.aspx?m=1
  2. http://forums.fedoraforum.org/showthread.php?t=293856
0
nobler1050

Здесь уже много ответов, но мы столкнулись с этим в очень конкретном случае и потратили много времени на расследование, поэтому добавили еще один. Мы видели это в следующем случае:

  • В докерном и тонком контейнере докера
  • Python по умолчанию 3.5.3 easy_install3
  • Для сертификатов LetsEncrypt, зарегистрированных с помощью cert-manager в нашем кластере Kubernetes

Команды pip3 и openssl смогли проверить сертификат, а easy_install3 смог успешно проверить другие сертификаты LetsEncrypt.

Обходной путь должен был собрать последний Python (3.7.3 в то время) из исходного кода. Инструкции здесь подробны и легки для выполнения.

0
aschmied

В моем случае я получал эту ошибку, потому что версии requests и urllib3 были несовместимы, что приводило к следующей ошибке во время установки:

ERROR: requests 2.21.0 has requirement urllib3<1.25,>=1.21.1, but you'll have urllib3 1.25 which is incompatible.
pip install 'urllib3<1.25' --force-reinstall

сделал свое дело.

0
fabio.sang

В python 2.7 помогло добавление сведений о доверенном корневом СА в конце файла C:\Python27\lib\site-packages\certifi\cacert.pem

после этого я запустил (используя права администратора) pip install --trusted-Host pypi.python.org --trusted-Host pypi.org --trusted-Host files.pythonhosted.org packageName

0
MD5

Для Linux Python3.6 это сработало для меня.

из командной строки установите pyopenssl и certifi

Sudo pip3 install -U pyopenssl
Sudo pip3 install certifi

и в моем скрипте python3 добавлено verify = '/ usr/lib/python3.6/site-packages/certifi/cacert.pem', например так:

import requests
from requests.auth import HTTPBasicAuth
import certifi

auth = HTTPBasicAuth('username', 'password')
body = {}

r = requests.post(url='https://your_url.com', data=body, auth=auth, verify='/usr/lib/python3.6/site-packages/certifi/cacert.pem')
0
Joe Jadamec

Python 2.7 на Amazon EC2 с CentOS 7

Я должен был установить переменную env SSL_CERT_DIR, чтобы она указывала на мой ca-bundle, который был расположен в /etc/ssl/certs/ca-bundle.crt

0
Brian McCall

Я нашел это более здесь

Я нашел это решение, вставьте этот код в начало вашего исходного файла:

import ssl

try:
   _create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
    # Legacy Python that doesn't verify HTTPS certificates by default
    pass
else:
    # Handle target environment that doesn't support HTTPS verification
    ssl._create_default_https_context = _create_unverified_https_context

Этот код отменяет проверку, поэтому сертификация ssl не проверяется.

0
Ganesh Chowdhary Sadanala

установка шагов для nltk (у меня уже был установлен python3 (3.6.2) в MAC OS X

Sudo easy_install pip

используйте игнорировать установленную опцию, чтобы игнорировать удаление предыдущей версии шести, иначе, это выдает ошибку при удалении и не перематывает фильм вперед

Sudo pip3 install -U nltk --ignore-installed six

Проверьте установку pip и python, используйте «3» версии

which python python2 python3
which pip pip2 pip3

Проверьте, установлен ли NLTK

python3
import nltk
nltk.__path__
['/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/nltk']

Установите SSL-сертификат перед установкой книги с примерами, иначе мы установим ошибку при установке примеров.

/Applications/Python\ 3.6/Install\ Certificates.command
python3 -m nltk.downloader book

Это успешно завершило установку nltk и nltk_ata для примеров книг

0
Narasimha Sai

Решение для Анаконды

Моя установка - Anaconda Python 3.7 на MacOS с прокси. Пути разные.

  • Вот как вы получаете правильный путь к сертификатам:
import ssl
ssl.get_default_verify_paths()

который в моей системе производится

Out[35]: DefaultVerifyPaths(cafile='/miniconda3/ssl/cert.pem', capath=None,
 openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/miniconda3/ssl/cert.pem',
 openssl_capath_env='SSL_CERT_DIR', openssl_capath='/miniconda3/ssl/certs')

Как только вы знаете, куда идет сертификат, вы объединяете сертификат, используемый прокси, до конца этого файла.

Я уже настроил conda для работы с моим прокси, запустив:

conda config --set ssl_verify <pathToYourFile>.crt

Если вы не помните, где находится ваш сертификат, вы можете найти его в ~/.condarc:

ssl_verify: <pathToYourFile>.crt

Теперь concatenate этот файл до конца /miniconda3/ssl/cert.pem и запросы должны работать, в частности sklearn.datasets и аналогичные инструменты должны работать.

Дальнейшие предостережения

Другие решения не работали, потому что установка Anaconda немного отличается:

  • Путь Applications/Python\ 3.X просто не существует.

  • Путь, предоставленный командами ниже, являетсяНЕВЕРНЫМpath

from requests.utils import DEFAULT_CA_BUNDLE_PATH
DEFAULT_CA_BUNDLE_PATH
0
Leo

Установка PyOpenSSL с использованием pip работала для меня (без конвертации в PEM):

pip install PyOpenSSL
0
averma93

Я решил эту проблему, закрыв проверку Fiddler (прокси-сервер отладки HTTP), если у вас включен прокси, и повторите попытку. 

0
vperezb

Установка certifi на Mac решила мою проблему:

pip install certifi
0
Snehal Parmar

Еще одно решение Anaconda. Я получал CERTIFICATE_VERIFY_FAILED в моей среде Python 2.7 на macOS. Оказывается, конда пути были плохими:

базовая (3.7) среда:

>>> import ssl
>>> ssl.get_default_verify_paths()
DefaultVerifyPaths(cafile='/usr/local/anaconda3/ssl/cert.pem', capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/local/anaconda3/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/local/anaconda3/ssl/certs')

2.7 окружение (пути не существовали!):

DefaultVerifyPaths(cafile='', capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/local/anaconda3/envs/py27/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/local/anaconda3/envs/py27/ssl/certs')

Исправление:

cd /usr/local/anaconda3/envs/py27/
mkdir ssl
cd ssl
ln -s ../../../ssl/cert.pem
0
Peter Tseng