Python Requests - ошибка SSL для сертификата на стороне клиента

Я вызываю REST API с запросами в Python и до сих пор был успешным, когда я установил verify=False,

Теперь мне нужно использовать сертификат клиента, который мне нужно импортировать для аутентификации, и я получаю эту ошибку каждый раз, когда использую cert (.pfx). cert.pfx защищен паролем.

r = requests.post(url, params=payload, headers=headers, 
                  data=payload, verify='cert.pfx')

Это ошибка, которую я получаю:

Traceback (most recent call last):
File "C:\Users\me\Desktop\test.py", line 65, in <module>
r = requests.post(url, params=payload, headers=headers, data=payload, verify=cafile)
File "C:\Python33\lib\site-packages\requests\api.py", line 88, in post
return request('post', url, data=data, **kwargs)
File "C:\Python33\lib\site-packages\requests\api.py", line 44, in request
return session.request(method=method, url=url, **kwargs)
File "C:\Python33\lib\site-packages\requests\sessions.py", line 346, in request
resp = self.send(prep, **send_kwargs)
File "C:\Python33\lib\site-packages\requests\sessions.py", line 449, in send
r = adapter.send(request, **kwargs)
File "C:\Python33\lib\site-packages\requests\adapters.py", line 322, in send
raise SSLError(e)
requests.exceptions.SSLError: unknown error (_ssl.c:2158)

Я также пытался OpenSSL, чтобы получить .pem и ключ, но с .pem и получать SSL: CERTIFICATE_VERIFY_FAILED

Может кто-нибудь подсказать, пожалуйста, как импортировать сертификаты и где их разместить? Я попытался найти, но все еще столкнулся с той же проблемой.

4 ответа

Решение

У меня была такая же проблема. verify Параметр, кажется, ссылается на сертификат сервера. Вы хотите cert Параметр для указания вашего сертификата клиента.

Мне пришлось использовать OpenSSL для конвертации, чтобы получить PEM-файл сертификата и PEM-файл ключа.

import requests
cert_file_path = "cert.pem"
key_file_path = "key.pem"

url = "https://example.com/resource"
params = {"param_1": "value_1", "param_2": "value_2"}
cert = (cert_file_path, key_file_path)
r = requests.get(url, params=params, cert=cert, verify=False)

У меня все еще были проблемы с запросами, не играющими хорошо с некоторыми серверами SSL, но я думаю, что verify / cert Различие может быть вашей проблемой.

У меня была та же проблема, и для ее решения я узнал, что нам нужно отправить RootCA вместе с сертификатом и его ключом, как показано ниже.

      response = requests.post(url, data=your_data, cert=('path_client_certificate_file', 'path_certificate_key_file'), verify='path_rootCA')

Можно ли перенести сертификат напрямую из хранилища сертификатов Windows? Насколько я понимаю, библиотека запросов принимает только путь к файлу. существуют ли какие-либо адаптеры или другие библиотеки, которые делают это так же просто, как запросы?

      cert_name = "NAME CERT IN CERT STORE"
def export_cert_to_pem(cert, pem_path):
    pem = cert.get_pem()

    with open(pem_path, "w") as pem_file:
        pem_file.write(pem)


def find_cert_in_trusted_roots(cert_name):
    for storename in ("CA", "ROOT"):
        with wincertstore.CertSystemStore(storename) as store:
            for cert in store.itercerts(usage=wincertstore.SERVER_AUTH):
                if cert.get_name().lower() == cert_name.lower():
                    export_cert_to_pem(cert, cert_name + ".pem")

                    #export_cert_to_pem(cert, pem_path)
                    return 1

    return 0




cert=find_cert_in_trusted_roots(cert_name)
response = requests.post(some_url, data=your_data, cert=cert)

У меня также была такая же проблема, но я работаю в операционной системе Windows в корпоративной среде с собственными сертификатами TSL или SSL. Я очень рекомендую использоватьpip_system_certsупаковка. Этот пакет перенаправляетrequests.get()использовать сертификаты хранилища операционной системы по умолчанию.

Установить пакет с:

pip install pip_system_certs

Мое решение заключалось в развертывании автономного исполняемого файла Python для загрузки файла, поэтому мне пришлось включитьimport pip_system_certs.wrapt_requests. Примечание,# noqa: F401заключается в том, чтобы игнорировать ошибку проверки flake8 только для этой строки.

      import sys
import os
# 'import pip_system_certs' must occur before 'import requests'
import pip_system_certs.wrapt_requests  # noqa: F401
import requests

if __name__ == "__main__":
  
  installerUrl = "https://www.python.org/ftp/python/3.10.8/python-3.10.8-amd64.exe"
  userPath = os.environ.get("USERPROFILE")
  installerPath = os.path.join(os.environ.get("USERPROFILE"), "temp_python_setup", os.path.basename(installerUrl))
  
  if not os.path.isdir(os.path.dirname(installerPath)):
    os.makedirs(os.path.dirname(installerPath))
  
  print(f"Installer Path='{installerPath}'")
  print(f"Installer URL='{installerUrl}'")
  
  downloadSuccessful = False
  proxy = {"http": "http://127.0.0.1:9000", "https": "http://127.0.0.1:9000"}
  
  try:
    with open(installerPath, "wb") as f:
      print("Downloading %s" % installerPath)
      response = requests.get(installerUrl,
                              stream=True,
                              verify=True,
                              allow_redirects=True,
                              proxies=proxy)
      totalSize = response.headers.get('content-length')
      if totalSize is None:  # no content length header
        f.write(response.content)
      else:
        totalSteps = 80
        downloadedSize = 0
        totalSize = int(totalSize)
        for data in response.iter_content(chunk_size=4096):
          downloadedSize += len(data)
          f.write(data)
          downloadedSteps = int(totalSteps * downloadedSize / totalSize)
          sys.stdout.write("\r[%s%s]" % ('=' * downloadedSteps, ' ' * (totalSteps - downloadedSteps)))
          sys.stdout.flush()
      downloadSuccessful = True
      print(" ")  # end the progress bar
  except Exception as e:
    print(" ")  # end the progress bar, which may or may not have been started
    print(f"Error downloading {installerUrl}: {repr(e)}")
  
  if downloadSuccessful:
    print("\nDownload completed successfully")
  else:
    print("\nDownload failed")
Другие вопросы по тегам