Перейти к содержимому

Как сделать авторизацию на сайте через flask

  • автор:

#18 Аутентификация во Flask

Аутентификация — один из самых важных элементов веб-приложений. Этот процесс предотвращает попадание неавторизованных пользователей на непредназначенные для них страницы. Собственную систему аутентификации можно создать с помощью куки и хэширования паролей. Такой миниатюрный проект станет отличной проверкой полученных навыков.

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

(env) gvido@vm:~/flask_app$ pip install flask-login 

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

Сейчас информация о пользователях, которые являются администраторами или редакторами сайта, нигде не хранится. Первая задача — создать модель User для хранения пользовательских данных. Откроем main2.py , чтобы добавить модель User после модели Employee :

#.. class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(100)) username = db.Column(db.String(50), nullable=False, unique=True) email = db.Column(db.String(100), nullable=False, unique=True) password_hash = db.Column(db.String(100), nullable=False) created_on = db.Column(db.DateTime(), default=datetime.utcnow) updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow) def __repr__(self): return ":<>>".format(self.id, self.username) #. 

Для обновления базы данных нужно создать новую миграцию. В терминале для создания нового скрипта миграции необходимо ввести следующую команду:

(env) gvido@vm:~/flask_app$ python main2.py db migrate -m "Adding users table" 

Запустить миграцию необходимо с помощью команды upgrade :

(env) gvido@vm:~/flask_app$ python main2.py db upgrade INFO [alembic.runtime.migration] Context impl MySQLImpl. INFO [alembic.runtime.migration] Will assume non-transactional DDL. INFO [alembic.runtime.migration] Running upgrade 6e059688f04e -> 0f0002bf91cc, Adding users table (env) gvido@vm:~/flask_app$ 

Это создаст таблицу users в базе данных.

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

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

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

pbkdf2:sha256:50000$Otfe3YgZ$4fc9f1d2de2b6beb0b888278f21a8c0777e8ff980016e043f3eacea9f48f6dea 

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

Вот процессы, которые задействованы при создании хэша пароля:

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

Flask поставляется с пакетом Werkzeug, в котором есть две вспомогательные функции для хэширования паролей.

Метод Описание
generate_password_hash(password) Принимает пароль и возвращает хэш. По умолчанию использует одностороннюю функцию pbkdf2 для создания хэша.
check_password_hash(password_hash, password) Принимает хэш и пароль в чистом виде, затем сравнивает password и password_hash . Если они одинаковые, возвращает True .

Следующий код демонстрирует, как работать с этими функциями:

>>> >>> from werkzeug.security import generate_password_hash, check_password_hash >>> >>> hash = generate_password_hash("secret password") >>> >>> hash 'pbkdf2:sha256:50000$zB51O5L3$8a43788bc902bca96e01a1eea95a650d9d5320753a2fbd16bea984215cdf97ee' >>> >>> check_password_hash(hash, "secret password") True >>> >>> check_password_hash(hash, "pass") False >>> >>> 

Стоит обратить внимание, что когда check_password_hash() вызывается с правильными паролем ( “secret password” ), возвращается True , а если с неправильными — False .

Дальше нужно обновить модель User , и добавить в нее хэширование паролей:

#. from werkzeug.security import generate_password_hash, check_password_hash #. #. class User(db.Model): #. updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow) def __repr__(self): return ":<>>".format(self.id, self.username) def set_password(self, password): self.password_hash = generate_password_hash(password) def check_password(self, password): return check_password_hash(self.password_hash, password) #. 

Создадим пользователей, чтобы проверить хэширование паролей.

(env) gvido@vm:~/flask_app$ python main2.py shell >>> >>> from main2 import db, User >>> >>> u1 = User(username='spike', email='spike@example.com') >>> u1.set_password("spike") >>> >>> u2 = User(username='tyke', email='tyke@example.com') >>> u2.set_password("tyke") >>> >>> db.session.add_all([u1, u2]) >>> db.session.commit() >>> >>> u1, u2 (1:spike>, 2:tyke>) >>> >>> >>> u1.check_password("pass") False >>> u1.check_password("spike") True >>> >>> u2.check_password("foo") False >>> u2.check_password("tyke") True >>> >>> 

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

Интеграция Flask-Login

Для запуска Flask-Login нужно импортировать класс LoginManager из пакета flask_login и создать новый экземпляр LoginManager :

#. from werkzeug.security import generate_password_hash, check_password_hash from flask_login import LoginManager app = Flask(__name__) app.debug = True app.config['SECRET_KEY'] = 'a really really really really long secret key' app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:pass@localhost/flask_app_db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['MAIL_SERVER'] = 'smtp.googlemail.com' app.config['MAIL_PORT'] = 587 app.config['MAIL_USE_TLS'] = True app.config['MAIL_USERNAME'] = 'youmail@gmail.com' app.config['MAIL_DEFAULT_SENDER'] = 'youmail@gmail.com' app.config['MAIL_PASSWORD'] = 'password' manager = Manager(app) manager.add_command('db', MigrateCommand) db = SQLAlchemy(app) migrate = Migrate(app, db) mail = Mail(app) login_manager = LoginManager(app) #. 

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

Метод Описание
is_authenticated() Возвращает True , если пользователь проверен (то есть, зашел с корректным паролем). В противном случае — False .
is_active() Возвращает True , если действие аккаунта не приостановлено.
is_anonymous() Возвращает True для неавторизованных пользователей.
get_id() Возвращает уникальный идентификатор объекта User .

Flask-Login предлагает реализацию этих методов по умолчанию с помощью класса UserMixin . Так, вместо определения их вручную, можно настроить их наследование из класса UserMixin . Откроем main2.py , чтобы изменить заголовок модели User :

#. from flask_login import LoginManager, UserMixin #. class User(db.Model, UserMixin): __tablename__ = 'users' #. 

Осталось только добавить обратный вызов user_loader . Соответствующий метод можно добавить над моделью User .

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

Функция, принимающая в качестве аргумента декоратор user_loader , будет вызываться с каждым запросом к серверу. Она загружает пользователя из идентификатора пользователя в куки сессии. Flask-Login делает загруженного пользователя доступным с помощью прокси current_user . Для использования current_user его нужно импортировать из пакета flask_login . Он ведет себя как глобальная переменная и доступен как в функциях представления, так и в шаблонах. В любой момент времени current_user ссылается либо на вошедшего в систему, либо на анонимного пользователя. Различать их можно с помощью атрибута is_authenticated прокси current_user . Для анонимных пользователей is_authenticated вернет False . В противном случае — True .

Ограничение доступа к просмотру

Пока что на сайте нет никакой административной панели. В этом уроке она будет представлена обычной страницей. Чтобы не допустить неавторизованных пользователей к защищенным страница у Flask-Login есть декоратор login_required . Добавим следующий код в файле main2.py сразу за функцией представления updating_session() :

#. from flask_login import LoginManager, UserMixin, login_required #. @app.route('/admin/') @login_required def admin(): return render_template('admin.html') #. 

Декоратор login_required гарантирует, что функция представления admin() вызовется только в том случае, если пользователь авторизован. По умолчанию, если анонимный пользователь попытается зайти на защищенную страницу, он получит ошибку 401 «Не авторизован».

Необходимо запустить сервер и зайти на https://localhost:5000/login , чтобы проверить, как это работает. Откроется такая страница:

Страница с ошибкой 401

Вместо того чтобы показывать пользователю ошибку 401, лучше перенаправить его на страницу авторизации. Чтобы сделать это, нужно передать атрибуту login_view экземпляра LoginManager значение функции представления login() :

#. migrate = Migrate(app, db) mail = Mail(app) login_manager = LoginManager(app) login_manager.login_view = 'login' class Faker(Command): 'A command to add fake data to the tables' #. 

Сейчас функция login() определена следующим образом (но ее нужно будет поменять):

#. @app.route('/login/', methods=['post', 'get']) def login(): message = '' if request.method == 'POST': print(request.form) username = request.form.get('username') password = request.form.get('password') if username == 'root' and password == 'pass': message = "Correct username and password" else: message = "Wrong username or password" return render_template('login.html', message=message) #. 

Если теперь зайти на https://localhost:5000/admin/ , произойдет перенаправление на страницу авторизации:

Страница авторизации во Flask

Flask-Login также настраивает всплывающее сообщение, когда пользователя перенаправляют на страницу авторизации, но сейчас никакого сообщения нет, потому что шаблон авторизации ( template/login.html ) не отображает никаких сообщений. Нужно открыть login.html и добавить следующий код перед тегом :

#. endif %> for category, message in get_flashed_messages(with_categories=true) %> spam class token property">category >>">message >>spam> endfor %> form action="" method="post"> #. 

Ошибка авторизации во Flask

Если снова зайти на https://localhost:5000/admin/ , на странице отобразится сообщение.

Чтобы изменить содержание сообщения, нужно передать новый текст атрибуту login_message экземпляра LoginManager .

Заодно почему бы не создать шаблон для функции представления admin() . Создадим новый шаблон admin.html со следующим кодом:

 html lang="en"> head> meta charset="UTF-8"> title>Titletitle> head> body> h2>Logged in User detailsh2> ul> li>Username: >li> li>Email: >li> li>Created on: >li> li>Updated on: >li> ul> body> html> 

Здесь используется переменная current_user для отображения подробностей о авторизованном пользователе.

Создание формы авторизации

Перед авторизацией нужно создать форму. В ней будет три поля: имя пользователя, пароль и запомнить меня. Откроем forms.py , чтобы добавить класс LoginForm под классом ContactForm :

#. from wtforms import StringField, SubmitField, TextAreaField, BooleanField, PasswordField #. #. class LoginForm(FlaskForm): username = StringField("Username", validators=[DataRequired()]) password = PasswordField("Password", validators=[DataRequired()]) remember = BooleanField("Remember Me") submit = SubmitField() 

Авторизация пользователей

Для авторизации пользователя Flask-Login предоставляет функцию login_user() . Она принимает объект пользователя. В случае успеха возвращает True и устанавливает сессию. В противном случае — False . По умолчанию сессия, установленная login_user() , заканчивается при закрытии браузера. Чтобы позволить пользователям оставаться авторизованными на дольше, нужно передать remember=True функции login_user() при авторизации пользователя. Откроем main2.py , чтобы изменить функцию представления login() :

#. from forms import ContactForm, LoginForm #. from flask_login import LoginManager, UserMixin, login_required, login_user, current_user #. @app.route('/login/', methods=['post', 'get']) def login(): form = LoginForm() if form.validate_on_submit(): user = db.session.query(User).filter(User.username == form.username.data).first() if user and user.check_password(form.password.data): login_user(user, remember=form.remember.data) return redirect(url_for('admin')) flash("Invalid username/password", 'error') return redirect(url_for('login')) return render_template('login.html', form=form) #. 

Дальше нужно обновить login.html , чтобы использовать класс LoginForm() . Нужно добавить в файл следующие изменения:

 html lang="en"> head> meta charset="UTF-8"> title>Logintitle> head> body> for category, message in get_flashed_messages(with_categories=true) %> spam class token property">category >>">message >>spam> endfor %> form action="" method="post"> form.csrf_token >> p> form.username.label() >> form.username() >> if form.username.errors %> for error in form.username.errors %> error >> endfor %> endif %> p> p> form.password.label() >> form.password() >> if form.password.errors %> for error in form.password.errors %> error >> endfor %> endif %> p> p> form.remember.label() >> form.remember() >> p> p> form.submit() >> p> form> body> html> 

Теперь можно авторизоваться. Если зайти https://localhost:5000/admin , произойдет перенаправление на страницу авторизации.

перенаправление на страницу авторизации

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

перенаправление на страницу администратора

Если не кликнуть “Remember Me” при авторизации, после закрытия браузера сайт выйдет из аккаунта. Если кликнуть, то логин останется.

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

Ошибка авторизации во Flask

Завершение сеансов пользователей (выход из аккаунтов)

Функция logout_user() во Flask-Login завершает сеанс пользователя, удаляя его идентификатор из сессии. В файле main2.py нужно добавить следующий код под функцией представления login() :

#. from flask_login import LoginManager, UserMixin, login_required, login_user, current_user, logout_user #. @app.route('/logout/') @login_required def logout(): logout_user() flash("You have been logged out.") return redirect(url_for('login')) #. 

Далее необходимо обновить шаблон admin.html , чтобы добавить ссылку на маршрут logout :

#. ul> li>Username:  current_user.username >>/li> li>Email:  current_user.email >>/li> li>Created on:  current_user.created_on >>/li> li>Updated on:  current_user.updated_on >>/li> /ul> p>a href=">">Logout/a>/p> /body> /html> 

Если сейчас зайти на https://localhost:5000/admin/ (будучи авторизованным), то в нижней части страницы должны быть ссылка для выхода из аккаунта.

Если ее нажать, произойдет перенаправление на страницу авторизации.

выход из аккаунта

Финальные штрихи

Есть одна маленькая проблема со страницей авторизации. Сейчас если авторизованный пользователь зайдет на https://localhost:5000/login/ , то он снова увидит страницу авторизации. Нет смысла в демонстрации формы авторизованному пользователю. Для разрешения этой проблемы нужно добавить следующие изменения в функцию представления login() :

#. @app.route('/login/', methods=['post', 'get']) def login(): if current_user.is_authenticated: return redirect(url_for('admin')) form = LoginForm() if form.validate_on_submit(): #. 

После этих изменений если авторизованный пользователь зайдет на страницу авторизации, он будет перенаправлен на страницу администратора.

  • ТЕГИ
  • Flask
  • Уроки по Flask на русском

Как сделать регистрацию на flask?

Добрый вечер.
Начал разбирать Flask, дошел до регистрации пользователей, не совсем понимаю что к чему. Просмотрел статью на хабре — habrahabr.ru/post/222983
Вообщем-то и разбирался по этим статьям, но не хочу делать регистрацию через OpenID, хочу классические логин/мыло-пароль.
С чего начать?

  • Вопрос задан более трёх лет назад
  • 9927 просмотров

Комментировать

Решения вопроса 0

Ответы на вопрос 3

Yuri Shikanov @dizballanze

Software developer at Yandex

Можно использовать Flask-Security, там все есть из коробки. Или самому написать при помощи Flask-WTF (формы), SQLAlchemy (ORM).

Ответ написан более трёх лет назад

Нравится 1 2 комментария

Аутентификация пользователей в приложении с помощью Flask-Login

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

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

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

Настройка и установка приложения

Исчерпывающее руководство по настройке и установке проекта можно найти в репозитории на GitHub.

Базовая структура приложения

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

Создание приложения

Для начала мы создадим функцию — фабрику приложений внутри файла app.py и назовем ее create_app . Это жизненно важно для любого приложения Flask.

Кроме того, нам нужно импортировать некоторые библиотеки для использования в нашем проекте:

app.py

from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_bcrypt import Bcrypt from flask_migrate import Migrate from flask_login import ( UserMixin, login_user, LoginManager, current_user, logout_user, login_required, )
  • Flask ,
  • SQLAlchemy , чтобы помочь нашему приложению Python взаимодействовать с базой данных,
  • Bcrypt для хеширования паролей,
  • Migrate для миграции базы данных,
  • несколько других методов из Flask-Login для управления сеансами.
login_manager = LoginManager() login_manager.session_protection = "strong" login_manager.login_view = "login" login_manager.login_message_category = "info"

Чтобы использовать Flask_login, мы создадим экземпляр, как показано выше. То же самое мы проделаем для SQLAlchemy, Migrate и Bcrypt.

db = SQLAlchemy() migrate = Migrate() bcrypt = Bcrypt()

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

Создавая экземпляр Flask внутри функции, мы сможем использовать несколько экземпляров приложения (в том числе и во время тестирования).

def create_app(): app = Flask(__name__) app.secret_key = 'secret-key' app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///database.db" app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True login_manager.init_app(app) db.init_app(app) migrate.init_app(app, db) bcrypt.init_app(app) return app

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

Теперь, когда с базовой фабрикой приложения покончено, пора объявить нашу модель User . В таблице пользователей нам нужны только столбцы электронной почты ( email ), имени пользователя ( username ) и пароля для этого приложения ( password ).

models.py

from app import db from flask_login import UserMixin class User(UserMixin, db.Model): __tablename__ = "user" primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) pwd = db.Column(db.String(300), nullable=False, unique=True) def __repr__(self): return '' % self.username

Мы импортируем db , экземпляр SQLAlchemy и подкласс UserMixin из Flask-Login.

Благодаря UserMixin наша работа упрощается. Он позволяет нам использовать такие методы, как is_authenticated() , is_active() , is_anonymous() и get_id() .

Не включив UserMixin в нашу модель User , мы получим ошибки. Например, ‘User’ object has no attribute ‘is_active’ .

В настоящее время у нас есть модель User , но мы еще не создали таблицу. Для этого запустите python manage.py в своем терминале в каталоге проекта. Но сначала убедитесь, что вы правильно всё настроили, установили пакеты из файла requirements.txt и имеете активную виртуальную среду.

manage.py

def deploy(): """Run deployment tasks.""" from app import create_app,db from flask_migrate import upgrade,migrate,init,stamp from models import User app = create_app() app.app_context().push() db.create_all() # migrate database to latest revision init() stamp() migrate() upgrade() deploy()

Функция deploy импортирует функцию create_app из файла app.py , методы миграции Flask-Migrate и модель User . Затем мы гарантируем, что работаем в контексте приложения, из которого теперь мы можем вызвать db.create all() , который и позаботится о создании нашей таблицы.

Еще нам нужно настроить формы входа и регистрации. Для начала следует подготовить две формы Flask, прежде чем отображать их в шаблоне. Конфигурация форм показана ниже.

Чтобы статья была аккуратной и точной, мы опустим строки импорта. Исключенные строки импорта можно посмотреть в репозитории GitHub.

forms.py

Форма регистрации
class register_form(FlaskForm): username = StringField( validators=[ InputRequired(), Length(3, 20, message="Please provide a valid name"), Regexp( "^[A-Za-z][A-Za-z0-9_.]*$", 0, "Usernames must have only letters, " "numbers, dots or underscores", ), ] ) email = StringField(validators=[InputRequired(), Email(), Length(1, 64)]) pwd = PasswordField(validators=[InputRequired(), Length(8, 72)]) cpwd = PasswordField( validators=[ InputRequired(), Length(8, 72), EqualTo("pwd", message="Passwords must match !"), ] )

В приведенном выше фрагменте кода мы просто применяем проверки к обязательным полям, импортированным из wtforms . Далее мы присваиваем их переменным полей формы.

def validate_email(self, email): if User.query.filter_by(email=email.data).first(): raise ValidationError("Email already registered!") def validate_uname(self, uname): if User.query.filter_by(username=username.data).first(): raise ValidationError("Username already taken!")

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

Форма входа
class login_form(FlaskForm): email = StringField(validators=[InputRequired(), Email(), Length(1, 64)]) pwd = PasswordField(validators=[InputRequired(), Length(min=8, max=72)]) # Placeholder labels to enable form rendering username = StringField( validators=[Optional()] )

Чтобы сделать поля формы видимыми в шаблоне, мы должны передать ему объект формы через маршрутизацию, отображающую этот шаблон. Пришло время определить различные маршруты нашего приложения. Строки импорта для этого раздела мы тоже опустим.

routes.py

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

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

В следующих строках кода мы просто определяем три маршрута для нашего приложения: index (для возврата домой), login (войти в систему) и register (зарегистрироваться).

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

# Home route @app.route("/", methods=("GET", "POST"), strict_slashes=False) def index(): return render_template("index.html",title="Home") # Login route @app.route("/login/", methods=("GET", "POST"), strict_slashes=False) def login(): form = login_form() return render_template("auth.html",form=form) # Register route @app.route("/register/", methods=("GET", "POST"), strict_slashes=False) def register(): form = register_form() return render_template("auth.html",form=form) if __name__ == "__main__": app.run(debug=True)

Теперь пришло время написать HTML-код. На данный момент все, что нам нужно, это формы, отображающиеся в браузере.

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

auth.html

>" method="POST" > >     
>
> > > > > > > >

New here? >">Create account Already have an account? >">Login

Этот HTML-шаблон служит как формой для входа, так и для регистрации. Мы просто использовали пару приемов для создания шаблонов jinja .

Как видите, для действия формы установлено значение action = «>» , где request.path извлекает путь, из которого возник запрос, и назначает его как значение для действия формы. Это избавляет от необходимости жестко прописывать определенные пути.

Мы также устанавливаем переменную токена csrf , которая позволяет продолжить проверку формы, предотвращая межсайтовую подделку запроса.

Кроме того, происходит обработка мигающих сообщений. Предупреждения Bootstrap 5 позволяют легко выводить разные сообщения в зависимости от их категории. Ниже приводится пример того, как это может выглядеть.

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

Еще одна вещь, которую следует учитывать, – это использование операторов if. else , например, в следующей строке кода:

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

Помните проверки, которые мы применяли к полям формы? Мы хотели бы уведомить пользователя, если он введет неверные данные. Поэтому давайте кое-что добавим.

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

Выглядеть это может так:

Как изменить routes.py

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

Маршрут регистрации

Прежде всего, внимательно изучите приведенный ниже фрагмент кода для регистрации новых пользователей. Тут мы подтверждаем, что форма, отправляющая данные, прошла все проверки. Итак, если form.validate_on_submit() :

. if form.validate_on_submit(): try: email = form.email.data pwd = form.pwd.data username = form.username.data newuser = User( username=username, email=email, pwd=bcrypt.generate_password_hash(pwd), ) db.session.add(newuser) db.session.commit() flash(f"Account Succesfully created", "success") return redirect(url_for("login")) except Exception as e: flash(e, "danger") .

Если все проверки пройдены, мы получаем значения из полей формы, которые затем передаются в объект User , добавляются в базу данных, и все изменения сохраняются.

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

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

Хранить пароли в виде обычного текста небезопасно, поскольку это увеличивает риск того, что учетные данные пользователя будут скомпрометированы в случае взлома.

Перед сохранением пароль пользователя хешируется, и в базе данных хранится хорошо зашифрованная комбинация символов. Справиться с этим нам поможет Bcrypt. Хеш создается следующим образом:

Маршрут входа

if form.validate_on_submit(): try: user = User.query.filter_by(email=form.email.data).first() if check_password_hash(user.pwd, form.pwd.data): login_user(user) return redirect(url_for('index')) else: flash("Invalid Username or password!", "danger") except Exception as e: flash(e, "danger")

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

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

Выход из системы

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

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

Заключение

Вот и все! Мы создали наше приложение с аутентификацией пользователя.

Спасибо за чтение! Мы надеемся, что эта статья была вам полезна.

Как реализовать простую авторизацию пользователя в приложении на Flask?

Для начала хотелось бы посмотреть, как авторизация пользователя будет работать без самой базы данных пользователей, т.е. проводить проверку при нажатии кнопки «Войти» на совпадение со значением, которое я определил заранее. Например, я создал условия входа, при котором логин пользователя должен быть таким: «Login». А пароль был таким: «Password» Буду любезен, если вы объясните эту столь сложноватую(лично для меня) тему.

Отслеживать
задан 17 дек 2019 в 12:08
Иван Иванов Иван Иванов
23 5 5 бронзовых знаков

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Общий принцип, по которому работает авторизация в УПРОЩЕННОМ виде:

  1. На странице логина принимаем от пользователя логин и пароль.
  2. На сервере проверяем их правильность (информация об этом может быть в базе данных, а может быть в глобальной переменной для упрощения).
  3. Генерируем авторизационный токен, длинную строку, которую сложно подделать, если никто, кроме клиента и сервера ее не знает. И связываем на сервере этот токен с уникальным именем пользователя.
  4. После чего устанавливаем на клиенте cookie, который будет посылаться вместе со всеми следующими запросами.

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

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

Отслеживать
ответ дан 18 дек 2019 в 3:52
3,082 2 2 золотых знака 12 12 серебряных знаков 21 21 бронзовый знак

  • python
  • flask
    Важное на Мете
Похожие

Подписаться на ленту

Лента вопроса

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.3.2953

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *