Для расширенных возможностей
авторизации, во Flask, существует расширение
Flask-Login
(
документация,
исходники
с примером).
В общих чертах
Расширение
Flask-Login
предназначено для упрощения управления
сессиями пользователей и решает типичные
задачи, такие как вход/выход, запоминание
сессий на определённый срок.
Что делает это расширение:
Хранит ID
залогинившихся пользователей внутри
сессии и позволяет достаточно просто
управлять их входом/выходом.
Позволяет
управлять доступом пользователей к
представлениям в зависимости от того,
залогинились они или нет.
Реализует функцию "запомнить
меня".
Что она не делает, а оставляет на нашей
совести:
Не навязывает
использование конкретных способов
хранения данных о пользователях.
Не ограничивает
в выборе способа авторизации и ничего
не мешает использовать логин/пароль,
OpenID или любой другой способ.
Не берет на
себя разграничением прав в зависимости
от залогинности пользователя.
Не выполняет регистрацию
пользователей и восстановление
пароля.
Начало использования
Первое что нужно сделать, для начала
работы с расширением, это создать в
любом месте программы, экземпляр класса
LoginManager:
login_manager
= LoginManager()
Класс
LoginManager
содержит код, который позволяет
организовать нюансы работы приложения
совместно с этим расширением. Например:
как загружать данные пользователя по
его ID, куда отправлять пользователей
когда они пытаются войти или выйти и
т.д.
Когда приложение полностью
сконфигурировано, необходимо передать
его в
LoginManager:
login_manager.setup_app(app)
Как строится работа
На каждого пользователя заводится
определённая структура (далее User), в
которой кроме прочих, нужных Вам данных
о пользователе, должен быть уникальный
ID и данные по которым можно авторизовать
пользователя (например логин/пароль).
И
Flask-Login
со своей стороны будет требовать от
Вас,
во-первых, найти объект User по
соответствующему ID, а
во-вторых,
найти и вернуть объект User по переданным
при авторизации данным.
Первое необходимо чтобы
найти объект User уже авторизованного
пользователя, при его последующих
запросах исходя из ID который хранится
в его сессии.
Для этого
необходимо назначить callback-функцию с
помощью декоратора
user_loader
которая используется расширением для
загрузки объекта User по его ID:
@login_manager.user_loader
def load_user(userid):
return User.get(userid)
Входной параметр один - строка unicode
содержащая ID пользователя. Функция
должна возвращать None, если ID не существует.
В противном случае, если все в порядке
и пользователь с там ID существует, нужно
вернуть соответствующий ему объект
User.
Второй случай происходит
на этапе авторизации пользователя,
когда Вы имеете некоторые данные (из
формы авторизации к примеру) и по ним
должны определить, корректны ли они и
существует ли пользователь им
соответствующий. И в этом случае, для
того чтобы
Flask-Login
поместил нужный ID в сессию пользователя,
Вы должны передать ему через функцию
login_user
объект User. Так же, через в эту функцию
можно передать параметр
remember
со значением
True, для
реализации функционала «запомнить
меня» - чтобы сессия
пользователя была восстановлена при
следующем входе, без авторизации.
Следующих
пример демонстрирует вариант авторизации
через логин/пароль. Поиск объекта User
осуществляется в функции get_user(login,
password).
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
login = request.form["login"]
password = request.form["password"]
remember_me = request.form["remember"]
# ищем пользователя по логину и паролю
# get_user - внутренняя функция, для запроса к БД, например
user = get_user(login, password)
if user:
# если пользователь с тамим логином и паролем существует -
# авторизуем и делаем редирект
login_user(user, remember=remember_me)
return redirect(url_for("index"))
return render_template("login.html")
Ограничение доступа к представлениям
Для ограничения доступа, чтобы к
представлению могли обращаться только
авторизованные пользователи, используется
декоратор
login_required.
При попытке перейти на URL представления
с таким декоратором, неавторизованный
пользователь будет отправлен на страницу
авторизации.
Завершение сеанса
Для того чтобы завершить сеанс
пользователя, существует функция
logout_user,
обратная по смыслу
login_user.
После её вызова куки из сессии пользователя
будут удалены и он будет считаться
неавторизованным. Вот пример использования:
@app.route("/logout")
@login_required
def logout():
logout_user()
return redirect(somewhere)
Итог
Таким образом подытожим основные
действия которые нужно выполнить для
добавления в своё приложение функции
авторизации:
- Определить механизм хранения и
создать набор пользователей, каждый
из которых будет иметь уникальный ID.
- Написать функцию с декоратором
user_loader
которая будет ставить в
соответствие ID конкретный объект
пользователя.
- Установить декоратор login_required
для представлений которые требуют
авторизации.
- Для авторизации добавить представление,
которое будет вызывать функцию login_user
с объектом пользователя если данные
для авторизации будут верны.
- Добавить представление, для
реализации выхода пользователя, которое
будет вызывать функцию logout_user.