Pi-code

Perl, Python и другие языки на букву "P"

Ноябрь 2007   Декабрь 2008   Январь 2009  

Подпишитесь на каналы Сообщения [Atom]

30.01.2009

 

Краулер своими руками. Часть 12

Как работает базовая аутентификация

Наряду с аутентификацией при помощи формы, существует и более простая -- так наз. "базовая аутентификация":
Пользователей заводит администратор веб-сервера. Их имена и пароли заносятся в конфигурацию. Они могут быть зашифрованы или храниться в виде текста -- зависит от требований к безопасности.

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


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

Базовая аутентификация и urllib2

Для базовой аутентификации средствами питоновской библиотеки urllib2 нужно использовать два встроенных класса:
Первый позволяет задавать имя пользователя и пароль, второй добавляется в набор handler-ов (обработчиков запроса) для специализированного экземпляра OpenDirector (см. подробности).

Простейший вариант HTTPPasswordMgr

class KnownPasswordMgr(HTTPPasswordMgr):
"""
Хранит заранее заданную пару логин/пароль
"""
def __init__(self, username, password):
HTTPPasswordMgr.__init__(self)
self.username = username
self.password = password

def find_user_password(self, realm, authuri):
"""
Возвращает заранее известную пару значений
"""
retval = HTTPPasswordMgr.find_user_password(self, realm, authuri)
if not (retval[0] or retval[1]):
return (self.username, self.password)

return retval
Этот класс рассчитан на использование одной единственной пары имя/пароль.

HTTPBasicAuthHandler

В конструктор класса UserAgent добавим необязательный параметр: credentials. Если он присутствует, к набору handler-ов будет добавлен HTTPBasicAuthHandler.

class UserAgent(object):
"""
Краулер.

Именованные аргументы конструктора и значения по умолчанию:
agentname -- имя ('Test/1.0')
email -- адрес разработчика (пустая строка)
hdrs -- словарь HTTP-заголовков (DEFAULT_HEADERS)
ignore_robots -- True, если следует игнорировать robots.txt (False)

credentials -- словарь с ключами 'логин' и 'пароль', если нужна
базовая аутентификация (None).
"""

def __init__(self,
agentname=DEFAULT_AGENTNAME,
email=DEFAULT_EMAIL,
hdrs=None,
ignore_robots=False,
credentials=None):

if not hdrs:
hdrs = {}
self.agentname = agentname
self.email = email

self.cookies_handler = SessionCookieHandler()
handlers = [ self.cookies_handler, ]
if not ignore_robots:
handlers.append(RobotsHTTPHandler(self.agentname))

if credentials:
handlers.append(
HTTPBasicAuthHandler(KnownPasswordMgr(**credentials))
)

self.opener = urllib2.build_opener(*handlers)

# переопределение заголовков по умолчанию
headers = copy(DEFAULT_HEADERS)
headers.update(hdrs)
op_headers = [ (k, v) for k, v in headers.iteritems() ]
op_headers.append(('User-Agent', self.agentname))
# если email не задан, HTTP-заголовок 'From' не нужен
if self.email:
op_headers.append(('From', self.email))

self.opener.addheaders = op_headers
Вот, собственно, и все. TestCase для новой функции может выглядеть так:

class TestAuth(unittest.TestCase):
def setUp(self):
self.crawler = crawler.UserAgent(
agentname='Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
ignore_robots=True,
credentials = dict(username='ЛОГИН', password='ПАРОЛЬ')
)

def _on_success(self, *args):
self.assertTrue(1)

def _on_failure(self, url, err):
self.fail('Authentication failed: %s' % err)

def test_authentication(self):
self.crawler.visit('АДРЕС САЙТА',
on_success=self._on_success,
on_failure=self._on_failure )
Здесь, в отличие от авторизации через форму, в случае успешного ответа не надо дополнительно проверять содержание страницы. В случае ошибки будет возвращаться все тот же код 401, т.е. функция обратного вызова _on_success не будет вызвана.

Ярлыки: , , , ,


Моя фотография
Имя: Сергей Крушинский
Местоположение: Москва, Russia

Зовите меня Наувул-Наувул, потому что живу я в соленой воде.



This page is powered by Blogger. Isn't yours?