python игнорировать проверку сертификата urllib2


Я хочу игнорировать certification validation во время моего запроса к серверу с внутренней корпоративной ссылкой.

С библиотекой python requests я бы сделал это:

r = requests.get(link, allow_redirects=False,verify=False)

Как сделать то же самое с библиотекой urllib2?

6 37

6 ответов:

Urllib2 по умолчанию не проверяет сертификат сервера. Проверьте эту документацию .

Edit: как указано в комментарии ниже, это больше не верно для более новых версий (похоже, > = 2.7.9) Python. См. ниже Ответ

В то же время urllib2, по-видимому, проверяет сертификаты сервера по умолчанию. Предупреждение , которое было показано в прошлом исчезла для версии 2.7.9, и в настоящее время я столкнулся с этой проблемой в тестовой среде с самозаверяющим сертификатом (и Python 2.7.9).

Мой злой обходной путь (не делайте этого в производстве!):

import urllib2
import ssl

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

urllib2.urlopen("https://your-test-server.local", context=ctx)

Согласно docs вызов конструктора SSLContext напрямую также должен работать. Я этого не пробовал.

Для тех, кто использует открывалку, вы можете добиться того же, основываясь на замечательном ответе Энно Грепера:

import urllib2, ssl

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

opener = urllib2.build_opener(urllib2.HTTPSHandler(context=ctx), your_first_handler, your_second_handler[...])
opener.addheaders = [('Referer', 'http://example.org/blah.html')]

content = opener.open("https://localhost/").read()

А затем использовать его, как и раньше.

Согласно build_opener и HTTPSHandler, HTTPSHandler добавляется, если модуль ssl существует, здесь мы просто указываем свой собственный вместо стандартного.

Самый простой способ:

Python 2

import urllib2, ssl

request = urllib2.Request('https://somedomain.co/')
response = urllib2.urlopen(request, context=ssl._create_unverified_context())

Python 3

from urllib.request import urlopen
import ssl

response = urlopen('https://somedomain.co', context=ssl._create_unverified_context())

Согласно сообщению @Enno Gröper, я попробовал конструктор SSLContext, и он хорошо работает на моей машине. код, как показано ниже:

import ssl
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
urllib2.urlopen("https://your-test-server.local", context=ctx)

Если вам нужен открыватель, просто добавьте этот контекст, например:

opener = urllib2.build_opener(urllib2.HTTPSHandler(context=ctx))

Примечание: все вышеописанные тестовые среды являются python 2.7.12. Я использую PROTOCOL_SSLv23 здесь, поскольку doc так говорит, другой протокол также может работать, но зависит от вашей машины и удаленного сервера, пожалуйста, проверьте doc для деталей.

Более явный пример, построенный на коде Дэмиена (вызывает тестовый ресурс в http://httpbin.org/). для python3. Обратите внимание, что если сервер перенаправляет на другой URL, uri в add_password должен содержать новый корневой URL (можно также передать список URL).

import ssl    
import urllib.parse
import urllib.request

def get_resource(uri, user, passwd=False):
    """
    Get the content of the SSL page.
    """
    uri = 'https://httpbin.org/basic-auth/user/passwd'
    user = 'user'
    passwd = 'passwd'

    context = ssl.create_default_context()
    context.check_hostname = False
    context.verify_mode = ssl.CERT_NONE

    password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
    password_mgr.add_password(None, uri, user, passwd)

    auth_handler = urllib.request.HTTPBasicAuthHandler(password_mgr)

    opener = urllib.request.build_opener(auth_handler, urllib.request.HTTPSHandler(context=context))

    urllib.request.install_opener(opener)

    return urllib.request.urlopen(uri).read()