Python запросов выбрасывает «ошибка проверки сертификата: невозможно получить сертификат локального эмитента» - PullRequest
0 голосов
/ 30 апреля 2020

При попытке вызвать API с помощью python Запросы я получаю ошибку certificate verify failed: unable to get local issuer certificate.

Я добавил сертификат SSL в cacert.pem сертификата. Это не решило проблему.

data = {'foo':'bar'}
url = 'hostname'
r = requests.post(url, data=data)

print(r) 

Приведенный выше код работает только тогда, когда я вставил verify = False в приведенном выше коде.

Я также извлек сертификат SSL API, используя приведенный ниже код, и добавил его в certifi cacert.pem , но это тоже не сработало.

import ssl, socket
myhostname = 'hostname'
myctx = ssl.create_default_context()
myctx.check_hostname = False
myctx.verify_mode = ssl.CERT_NONE
s = myctx.wrap_socket(socket.socket(), server_hostname=myhostname)
s.connect((myhostname, 443))

bcert = s.getpeercert(binary_form=True)
cert = ssl.DER_cert_to_PEM_cert(bcert)

Ниже приведена ошибка, которая выдается

Traceback (most recent call last):
  File "C:\Users\user\AppData\Local\Programs\Python\Python38-32\lib\site-packages\urllib3\connectionpool.py", line 670, in urlopen
    httplib_response = self._make_request(
  File "C:\Users\user\AppData\Local\Programs\Python\Python38-32\lib\site-packages\urllib3\connectionpool.py", line 381, in _make_request
    self._validate_conn(conn)
  File "C:\Users\user\AppData\Local\Programs\Python\Python38-32\lib\site-packages\urllib3\connectionpool.py", line 976, in _validate_conn
    conn.connect()
  File "C:\Users\user\AppData\Local\Programs\Python\Python38-32\lib\site-packages\urllib3\connection.py", line 361, in connect
    self.sock = ssl_wrap_socket(
  File "C:\Users\user\AppData\Local\Programs\Python\Python38-32\lib\site-packages\urllib3\util\ssl_.py", line 377, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "C:\Users\user\AppData\Local\Programs\Python\Python38-32\lib\ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "C:\Users\user\AppData\Local\Programs\Python\Python38-32\lib\ssl.py", line 1040, in _create
    self.do_handshake()
  File "C:\Users\user\AppData\Local\Programs\Python\Python38-32\lib\ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1108)

1 Ответ

1 голос
/ 30 апреля 2020

Я также извлек SSL-сертификат API

Я предполагаю, что вы использовали сертификат конечного сервера в качестве CA, и это не так, как работает проверка сертификата. Библиотека SSL на вашей стороне пытается построить цепочку доверия. Типичная цепочка сертификатов сервера выглядит следующим образом:

(CA ->) Промежуточный CA -> сертификат сервера

Сертификат CA не отправляется в процессе TLS-квитирования с сервером. Задача вашего ssl-клиента - найти подходящий доверенный ЦС для цепочки.

Вы должны добавить CA в CA_BUNDLE, а не в лист сертификата сервера.

Как получить сертификат CA? Попробуйте в браузере и нажмите на замок, сертификат CA будет самым верхним в цепочке, если он найден.

Вы также можете проверить сертификат и узнать, кто его подписал (атрибут эмитента). Возможно, вы сможете найти сертификат этого эмитента в некоторой общедоступной базе данных c CA.

...