получить пакет сертификатов urllib.requests, используемый с urlopen

Я работаю в Windows и вижу разницу между urllib.requests.urlopen и пакетом запросов при вызовах на один и тот же сайт.

Когда я выполняю следующее:

import urllib.request
f = urllib.request.urlopen('https://<domain certificated server> ')


Я могу добраться до своего сервера без проблем.

Когда я делаю:

import requests
f = requests.get('https://<domain certificated server> ').text

Я получаю сообщение об ошибке сертификата SSL. Я знаю, что это вызвано certifi. Итак, мой вопрос заключается в следующем: как я могу использовать все, что делает код Python, и использовать это более certifi в запросах?


person JabberJabber    schedule 09.10.2020    source источник
comment
Вы обновили сертификат? Прочтите 2.python-requests.org/en/master/ user/advanced/#ca-certificates — подтвердили ли вы, что urllib действительно проверяет действительный сертификат — если это не так, проблема связана с urllib, а не с запросами. Если вас не волнует проверка сертификата (например, использование интрасети), вы всегда можете отключить ее и в запросах.   -  person barny    schedule 09.10.2020
comment
Да, я обновил сертификат   -  person JabberJabber    schedule 09.10.2020
comment
@TrollGamingDude-__- я пытаюсь заставить библиотеку запросов работать с тем же хранилищем сертификатов, что и urllib.request.urlopen. Мне нравится интерфейс запросов, но мне нужна стандартная проверка сертификата библиотеки.   -  person JabberJabber    schedule 09.10.2020
comment
Вы проверили, действительно ли сертификат действителен? Вы можете просмотреть его в своем браузере.   -  person barny    schedule 09.10.2020
comment
сертификат действителен. Это сертификат домена, никаких ошибок в chrome, firefox и Edge (вздох, я знаю)   -  person JabberJabber    schedule 09.10.2020
comment
По какому URL вы обращаетесь? Какая версия питона? Запросы?   -  person barny    schedule 09.10.2020
comment
Это только внутренний сервер, поэтому я не могу его предоставить (извините за это), но я использую Python 3.6.10 и 3.7.6. Для запросов я использую последнюю версию и последнюю версию сертификата. (обновил это вручную)   -  person JabberJabber    schedule 09.10.2020
comment
Certifi определенно более актуален, чем urllib в Python 3.6.10 и 3.7.6. Итак, у этого внутреннего сервера есть имя хоста, которое (в сети, в которой он находится) разрешается вашему серверу, и это имя хоста соответствует имени хоста в сертификате?   -  person barny    schedule 09.10.2020
comment
да, это правильно   -  person JabberJabber    schedule 12.10.2020


Ответы (2)


Есть ли у вас возможность получить файл .pem с сертификатами сервера?

urlopen использует ssl.enum_certificates в Windows для загрузки сертификатов . Итак, сертификаты получены из службы Windows.

Как только вы получите файл сертификата, используйте его при вызове requests.get('<server.internal>', verify='/path/to/certfile')

person pbacterio    schedule 21.10.2020
comment
Я могу перечислить сертификаты, но не могу получить запросы на их использование. - person JabberJabber; 18.11.2020

простой способ состоит в том, чтобы указать requests использовать системный пакет, если вы знаете, где он находится. В Linux это обычно /etc/ssl/certs/ca-certificates.crt.

requests.get('<server.internal>', verify='/etc/ssl/certs/ca-certificates.crt')

Вы также можете определить свой собственный адаптер, если вы работаете в Windows, не знаете, где находится системный пакет, или просто хотите поддерживать все случаи. адаптер по умолчанию указывает urllib3 загружать сертификаты из DEFAULT_CA_BUNDLE_PATH который исходит от вызова certifi.where(). Если вы не сообщите urllib3, где взять сертификаты, он использовать системное значение по умолчанию.

import requests
import requests.adapters

class SysCertsHTTPAdapter(requests.adapters.HTTPAdapter):
  def cert_verify(self, conn, url, verify, cert):
    # require verification, but use system defaults
    # default requests implementation sets conn.ca_certs and/or conn.ca_cert_dir
    conn.cert_reqs = 'CERT_REQUIRED'


session = requests.Session()
session.mount('https://', SysCertsHTTPAdapter())
session.get("https://google.com")
person kichik    schedule 22.10.2020
comment
Я считаю, что это не сработало. Проблема в том, что urllib3 по умолчанию использует местоположение certifi.where(). - person JabberJabber; 22.10.2020
comment
Что заставляет вас так говорить? Он вызывает load_default_certs(), который использует системные местоположения. В документации указано, что вы должны вручную используйте ceritfi, а этот код - нет. - person kichik; 22.10.2020