вторник, 12 января 2010 г.

Аутентификация в web.py

Довольно редко можно встретить сайт в интернете у которого нет возможности регистрации пользователей. Форумы, блоги, интернет-магазины, социальные сети обязуют или рекомендуют своим пользователям пройти процедуру регистрации (аутентификации).

Рассмотрим один из способов реализации аутентификации на базе фреймворка web.py с помощью базового модуля session.py.



Для доступа к ресурсам сайта используются следующие URI:

/ или любые другие ссылки с помощью которых пользователь получает доступ к ресурсам сайта. Для упрощения рассмотрим только '/'.
/login - отображает форму аутентификации
/logout - закрывает сессию пользователя и переходит к форме аутентификации
urls = (
'/', 'index',
'/login', 'libs.auth.login',
'/logout', 'libs.auth.logout',
)

Для того чтобы при каждом обращении '/' происходила проверка статуса сессии задекорируем функцию index() декоратором @login_required.
class index:        
@login_required
def GET(self):
...

Каждый раз при обращении по GET запросу экземпляра класса index будет вызываться функция login_required:
def login_required(func):
def decorator(*args, **kargs):
try:
if web.config._sessions.logged_in:
return func(*args, **kargs)
else:
raise SessionExpired()
except AttributeError:
raise SessionExpired()
return func(*args, **kargs)
return decorator

Эта функция делает проверку был ли аутентифицирован пользователь или нет (web.config._session.logged_in и AttributeError). Если нет, вызывается исключение SessionExpired и произойдет автоматическая переадресация на форму аутентификации '/login'. Класс SessionExpired является базовым и входит в состав модуля session.py. Для того, чтобы выполнить переадресацию этот класс нужно переопределить.
class SessionExpired(web.HTTPError): 
def __init__(self, *args, **kargs):
web.HTTPError.__init__(self, '303 See Other', {'Location': '/login'})

Далее, сразу после подключения обработки сессий, базовый SessionExpired нужно подменить на новый:
if __name__ == "__main__":
app = web.application(urls, globals())
web.config._sessions = web.session.Session(app, DBStore('sessions'), initializer={})
web.session.SessionExpired = SessionExpired
app.run()

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

Сервер получает данные формы в запросе POST:
class login:
def GET(self):
return login_form()

def POST(self):
from hashlib import md5

username = web.input().username
password = md5(web.input().password).hexdigest()
users =  db.select('users', 
limit=1, 
where="username=$username AND password = $password", 
vars=locals())
try:
user = users[0]
web.config._sessions.username = user.username
web.config._sessions.privilege = user.privilege
web.config._sessions.logged_in = True
except IndexError:    
return login_form(username = username, 
error_msg='Unknown username or wrong password')
raise web.session.SessionExpired()

В методе POST осуществляется проверка имени пользователя и пароля с данными хранящимися в базе данных. Если данная проверка успешна, данные пользователя сохраняются в переменных сессии для данного пользователя.

О аутентификации более подробно можно узнать на wikipedia http://ru.wikipedia.org/wiki/Аутентификация

О декораторах
http://devel.ownport.net/2010/01/python-2.html
http://devel.ownport.net/2010/01/python.html

Дополнительная информация и примеры других решений
http://jpscaletti.com/webpy_auth/
http://webpy.infogami.com/authentication
http://dumpz.org/356/

0 комментариев:

Отправить комментарий