Как выполнить аутентификацию пользователя с помощью Flask-Login – CodesCode

Узнайте о возможностях, которые предлагает Flask-Login, и как использовать их для создания безопасной функциональности входа для пользователей в вашем веб-приложении на языке Python.

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

Аутентификация является важной частью любого веб-приложения, которое позволяет пользователям получать доступ к данным или ресурсам, так как она гарантирует, что доступ к конфиденциальной информации получают только правильные люди. Это также можно сделать в Flask с помощью Flask-Login.

Flask-Login – это расширение Flask с функциями, которые обрабатывают вход и выход пользователей и отслеживают текущего пользователя(ей) во всем приложении. Это упрощает реализацию аутентификации и авторизации в ваших приложениях Flask.

Почему использовать Flask-Login?

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

  • Управление сеансами пользователей. Flask-Login обрабатывает создание и уничтожение сеансов пользователей. Он также может сохранять идентификатор текущего пользователя в сеансе, чтобы вы могли легко проверить, вошел ли пользователь в систему.

  • Функциональность входа и выхода. Flask-Login предоставляет встроенные функции входа и выхода. Эти функции заботятся обо всех важных процессах: создание и уничтожение сеансов и перенаправление пользователя на соответствующую страницу.

  • Обратный вызов загрузчика пользователя. Flask-Login позволяет определить функцию обратного вызова загрузчика пользователя. Этот обратный вызов используется для загрузки объекта пользователя для текущего сеанса. Это полезно, если вы используете базу данных для хранения информации о пользователях.

  • Аутентификация и авторизация. Flask-Login упрощает реализацию аутентификации и авторизации в ваших приложениях. Вы можете использовать Flask-Login, чтобы защитить конкретные страницы или маршруты и предоставить пользователям различные уровни доступа к вашему приложению.

Требования

Чтобы следовать за этой статьей, вам понадобится следующее:

  • знание синтаксиса Python и Flask
  • базовое знание HTML и CSS
  • установленная версия Python 3 и Flask

Очевидно, вам также понадобится доступ к веб-браузеру.

Начало работы

Для полного использования модуля Flask-Login нам нужно установить Flask-Login и другие необходимые зависимости. Эти библиотеки предоставляют необходимые функции и инструменты для улучшения функциональности вашего приложения. Чтобы установить их, откройте командную строку или терминал и выполните следующую команду pip:

pip install flask-login flask_sqlalchemy flask_bcrypt

Вот разбор того, для чего каждая из этих библиотек используется:

  • Flask-SQLAlchemy: интегрирует SQLAlchemy с Flask для работы с базой данных
  • Flask-Bcrypt: добавляет хеширование bcrypt для обеспечения безопасности паролей в Flask

После завершения установки Flask login будет автоматически загружен в каталог, который вы использовали.

Примечание: на момент написания этой статьи есть небольшая проблема с разрешением зависимостей в последней версии Flask и Werkzeug. Чтобы решить эту проблему, вам нужно принудительно установить версию 2.3.0 Werkzeug, так как это единственная известная версия, которая работает в данный момент.

После установки зависимостей вам нужно будет инициализировать их с помощью вашего Flask-приложения:

from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin, LoginManager, login_user, logout_user, login_required
from flask_bcrypt import Bcrypt
from flask_login import LoginManager 
app = Flask(__name__)
login_manager = LoginManager()
login_manager.init_app(app)  

В приведенном кодовом фрагменте мы также инициализировали объект LoginManager в нашем приложении. LoginManager – это расширение Flask-Login, которое используется для настройки необходимых конфигураций для работы с пользовательскими сеансами.

Создание модели пользователя

Модель представляет собой представление структуры данных, которую вы хотите использовать в вашем приложении. Она определяет, как данные организованы, хранятся и обрабатываются в системе. Модели обычно используются с базой данных, которая следует структуре, определенной заранее. Для нашего приложения у нас есть следующие данные:

  • уникальный идентификатор
  • имя пользователя
  • пароль (хэшированный)
class User(UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True)
    password_hash = db.Column(db.String(128))
    
    def __repr__(self):
        return f'<User {self.username}>'

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

Создание базы данных

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

В этой статье мы будем использовать базу данных SQLite. Это связано с тем, что SQLite – это легкий и безсерверный движок баз данных. Это облегчает настройку и использование, так как он не требует отдельной установки. Он также является хорошим выбором для небольших и средних приложений.

Вот список шагов для использования базы данных SQLite в нашем приложении:

  1. Для использования базы данных SQLite вам необходимо установить URI в конфигурации вашего приложения Flask. Обычно это делается вверху, вместе с другими конфигурациями. Вот фрагмент, который вы можете использовать:

    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db' # Использование SQLite в качестве базы данных

    В этом фрагменте ///... указывает на относительный путь к вашему файлу – site.db – который является именем, которое мы использовали для файла базы данных SQLite. Это имя можно изменить на любое другое.

  2. Затем вам нужно инициализировать ORM Flask-SQLAlchemy с помощью этого фрагмента:

    db = SQLAlchemy(app)

    SQLAlchemy – это объектно-реляционный маппер, который предоставляет набор инструментов для работы с базами данных с использованием Python. Строка db = SQLAlchemy(app) создает экземпляр класса SQLAlchemy и связывает его с вашим приложением Flask (app).

  3. Для создания этой базы данных мы должны инициализировать базу данных, используя метод create_all:

    if __name__ == '__main__':
        db.create_all()
        app.run(debug=True)

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

    В данном случае код создаст файл site.db с таблицей User, если он еще не существует. Файл site.db обычно находится в папке /instance/.

    Структура файлов нашего приложения

Затем нам нужно создать user_loader, который принимает идентификатор пользователя и возвращает соответствующий объект User. Вот пример:

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(user_id)

Хэширование пароля

Хэширование пароля – это мера безопасности, которая сохраняет криптографическое представление пароля пользователя, прежде чем он будет сохранен в базе данных. Таким образом, становится труднее получить фактический пароль, даже если безопасность приложения была нарушена.

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

Как хешировать и проверять пароли с помощью Flask-Bcrypt

Flask имеет расширение под названием Flask-Bcrypt, которое помогает достичь этой функциональности. Оно имеет две основные функции: generate_password_hash() и check_password_hash().

Функция generate_password_hash() принимает пароль пользователя в качестве аргумента и возвращает хешированный пароль. Обычно это используется в логике регистрации.

Функция check_password_hash() принимает пароль и хешированный пароль в качестве аргументов и возвращает true, если два пароля совпадают, или false, если они не совпадают. Это выполняется перед предоставлением доступа к странице входа

Создание представления для регистрации

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

@app.route('/register', methods=['GET', 'POST'])def  register():if request.method == 'POST':  username = request.form['username']  password = request.form['password']  hashed_password = bcrypt.generate_password_hash(password).decode('utf-8') new_user = User(username=username,password=hashed_password)     db.session.add(new_user)    db.session.commit()    return redirect(url_for('welcome '))  return render_template('registeration.html')

Вот разбор кода:

  • В первой строке мы определяем маршрут для URL-пути /login. Этот маршрут принимает как GET-, так и POST-запросы. Функция login(), связанная с маршрутом, будет выполнена при запросе.

  • Затем мы проверяем, является ли метод запроса методом POST:

    if request.method == 'POST':

    После подтверждения функция извлекает значения, введенные пользователем в форму входа:

    username = request.form['username']password = request.form['password']
  • Затем она запрашивает базу данных на наличие пользователя с заданным именем пользователя. Если пользователь с заданным именем пользователя найден и пароль совпадает, код внутри этого блока будет выполнен.

Создание представления для входа

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

@app.route('/login', methods=['GET', 'POST'])def  login():  if request.method == 'POST':    username = request.form['username']    password = request.form['password']    user = User.query.filter_by(username=username).first()    if user and bcrypt.check_password_hash(user.password, password):    login_user(user)      return redirect(url_for('welcome'))  return render_template('login.html')

Вот разбор работы кода:

  • В первой строке — @app.route('/login', methods=['GET', 'POST']): — мы использовали декоратор, который определяет маршрут для URL-пути /login. Этот маршрут принимает как GET-, так и POST-запросы. Связанная функция login() будет выполнена при запросе к этому маршруту.

  • Функция login() начинается с проверки, является ли метод запроса POST:

    if request.method == 'POST':

    После подтверждения того, что это POST-запрос, она получает значения, введенные пользователем в форму входа:

    username = request.form['username']password = request.form['password']
  • Затем она запрашивает базу данных на наличие пользователя с заданным именем пользователя:

    user = User.query.filter_by(username=username).first()if user and bcrypt.check_password_hash(user.password, password):  
  • Если и имя пользователя, и пароль проверены, пользователю предоставляется доступ с использованием функций Flask-Login login_user и redirect:

    login_user(user)redirect(url_for('welcome'))
  • Однако, если метод request не является POST или данные неверны, он отображает шаблон login.html:

    return render_template('login.html')

    По сути, это проверяет, являются ли введенные данные верными, входит ли пользователь в систему и перенаправляет его на страницу приветствия в случае успеха. Если вход не удался или это GET-запрос, шаблон входа отображается для ввода учетных данных.

Создание логики выхода с использованием защищенного представления

В большинстве приложений некоторые страницы недоступны, если пользователь не вошел в систему. Сюда входят страницы, такие как история транзакций, черновики и страницы выхода из системы. Flask-Login предоставляет удобный способ защиты этих страниц/маршрутов и ограничения доступа только для аутентифицированных пользователей с помощью декоратора login_required. Вот как это работает.

Чтобы воспользоваться этой функциональностью, вам нужно импортировать декоратор login_required из Flask-Login:

from flask_login import login_required

Затем вам нужно добавить декоратор login_required к любому маршруту, который вы хотите защитить. Например, создадим страницу выхода из системы, которая может быть доступна только при входе пользователя в систему:

@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('login'))

Вот как это работает:

  • Как и в представлении для входа в систему, @app.route('/logout') определяет маршрут для пути URL /logout.

  • Затем мы добавляем декоратор login_required, который гарантирует, что пользователь должен быть авторизован для доступа к маршруту logout. Если пользователь не вошел в систему и попытается получить доступ к этому маршруту, он будет перенаправлен на страницу входа.

  • Внутри функции logout вызывается функция logout_user(). Эта функция предоставляется Flask-Login и используется для выхода текущего пользователя из системы.

  • После выхода пользователя из системы, функция перенаправляет его на маршрут login с помощью redirect(url_for('login')).

Таким образом, когда пользователь получает доступ к маршруту /logout, Flask-Login гарантирует, что он вошел в систему (@login_required), выходит из системы и перенаправляет его на страницу входа. Это помогает обеспечить безопасный выход пользователя из вашего Flask-приложения. Декоратор login_required применяется к маршруту /protected, указывая, что к нему можно получить доступ только аутентифицированным пользователям. И если пользователь попытается получить доступ к защищенной странице без авторизации, Flask-Login перенаправит его на страницу входа.

Добавление шаблонов

Шаблоны в Flask позволяют использовать HTML-страницы для определения внешнего вида вашего сайта. Чтобы полностью реализовать логику в нашем файле app.py, мы создадим следующие HTML-страницы.

Структура файлов нашего приложения

Анимация ниже показывает, как шаблоны отображают разные страницы нашего сайта.

https://player.vimeo.com/video/884411943

Вы можете увидеть полный код этого руководства и узнать больше о его реализации в репозитории GitHub этой статьи.

Как Flask-Login управляет сеансами пользователей с помощью сессионных куки пользователей

Сеанс пользователя – это система, которая отслеживает и обновляет информацию о пользователе во время его входа в систему. Flask-Login управляет этими сеансами, сохраняя сессионные куки на браузере пользователя. Сессионная кука представляет собой небольшую частицу данных, содержащую уникальный идентификатор сеанса пользователя.

Когда пользователь входит на веб-сайт с использованием Flask-Login, сервер создает сессионную куку и отправляет ее в браузер пользователя. Браузер сохраняет сессионную куку и включает ее во все запросы на сервер. Сервер использует сессионную куку для идентификации пользователя и его состояния сеанса.

Например, если пользователь вошел в систему и посещает страницу, защищенную Flask-Login, Flask-Login проверит сессионную куку, чтобы узнать, аутентифицирован ли пользователь. Если пользователь аутентифицирован, Flask-Login загрузит информацию о профиле пользователя из базы данных и сделает ее доступной представлению. Если пользователь не аутентифицирован, Flask-Login перенаправит пользователя на страницу входа.

Когда пользователь выходит из веб-сайта, сервер удаляет сеансовый cookie из браузера пользователя, что завершает пользовательскую сессию.

Заключение

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

Поделиться этой статьей


Leave a Reply

Your email address will not be published. Required fields are marked *