поддерживает ли urllib2 аутентификацию с упреждающей аутентификацией? - PullRequest
2 голосов
/ 07 января 2011

Я пытаюсь получить доступ к REST API.

Я могу заставить его работать в Curl / REST Client (инструмент пользовательского интерфейса) с включенной преимущественной проверкой подлинности.

Но, используя urllib2, онкажется, не поддерживает это по умолчанию, и я не могу найти способ включить его.

Спасибо:)

Ответы [ 3 ]

7 голосов
/ 15 декабря 2011

Вот простой базовый обработчик аутентификации Preemptive HTTP, основанный на коде из urllib2.HTTPBasicAuthHandler. Его можно использовать точно таким же образом, за исключением того, что заголовок Authorization будет добавлен к каждому запросу с соответствующим URL-адресом. Обратите внимание, что этот обработчик должен использоваться с HTTPPasswordMgrWithDefaultRealm. Это потому, что нет никакого царства, возвращающегося в WWW-Authenticate вызове, потому что вы упреждающий.

class PreemptiveBasicAuthHandler(urllib2.BaseHandler):

        def __init__(self, password_mgr=None):
                if password_mgr is None:
                        password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
                self.passwd = password_mgr
                self.add_password = self.passwd.add_password

        def http_request(self,req):
                uri = req.get_full_url()
                user, pw = self.passwd.find_user_password(None,uri)
                #logging.debug('ADDING REQUEST HEADER for uri (%s): %s:%s',uri,user,pw)
                if pw is None: return req

                raw = "%s:%s" % (user, pw)
                auth = 'Basic %s' % base64.b64encode(raw).strip()
                req.add_unredirected_header('Authorization', auth)
                return req
4 голосов
/ 05 июня 2014

похоже на ответ @ thom-nichols;но подкласс HTTPBasicAuthHandler также обрабатывает HTTPS-запросы.

import urllib2
import base64

class PreemptiveBasicAuthHandler(urllib2.HTTPBasicAuthHandler):
    '''Preemptive basic auth.

    Instead of waiting for a 403 to then retry with the credentials,
    send the credentials if the url is handled by the password manager.
    Note: please use realm=None when calling add_password.'''
    def http_request(self, req):
        url = req.get_full_url()
        realm = None
        # this is very similar to the code from retry_http_basic_auth()
        # but returns a request object.
        user, pw = self.passwd.find_user_password(realm, url)
        if pw:
            raw = "%s:%s" % (user, pw)
            auth = 'Basic %s' % base64.b64encode(raw).strip()
            req.add_unredirected_header(self.auth_header, auth)
        return req

    https_request = http_request

вот пример для работы с сервером jenkins, который не отправляет вам 401 http-ошибок (повторите попытку с auth)Я использую urllib2.install_opener, чтобы упростить задачу.

jenkins_url = "https://jenkins.example.com"
username = "johndoe"
api_token = "some-cryptic-value"

auth_handler = PreemptiveBasicAuthHandler()
auth_handler.add_password(
    realm=None, # default realm.
    uri=jenkins_url,
    user=username,
    passwd=api_token)
opener = urllib2.build_opener(auth_handler)
urllib2.install_opener(opener)
0 голосов
/ 07 января 2011

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

...