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

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

  • автор:

Tech Monger

In this tutorial we will learn how to build simple user authentication mechanism in Flask without using any login extensions. It’s good idea to use existing extensions however if you want more control over how user session cookies are getting handled or if you are not sure about working of an existing extensions then you can quickly roll out your own code to build something very simple. We will make use of Flask-SqlAlchemy to read and write into the database.

Application Structure

  • User DB — Store user details inside sqlite database.
  • Sign Up Form — Creating new users.
  • Login Form — User Login.
  • Home Page — Home page for authorized users.
  • Logout route — To logout users by removing cookie.

You can follow complete tutorial or directly jump into the python code. At the end of the tutorial we will push working code on github.

User Database

We will create authentication database auth.db in Sqlite with single table User . This table will have following three columns.

Column Description
uid (pk) Integer primary key for each user.
username (unique) String username with unique constraint assigned to it
pass_hash String to store password hash of user password

We will create auth.db with following User model using Flask Sqlalchemy.

Create empty db with User table

Templates

We will create following three jinja2 templates to serve html pages.

Signup Form
Login Form
User Home Page

Simple Hello User page for authorized user with logout link.

Login App with Flask Session

  1. We will authenticate user on login and store session cookie for user’s session.
  2. This session cookie will set value username equal to True. For example if Bob logs in successfully then we will store session[«Bob»]=True .
  3. For subsequent requests from Bob we will check value of session[«Bob»] . We will only allow Bob to access his home page if value is True .
  4. If there is no Bob cookie or Bob cookie with Value other than True then will abort request with HTTP 401 .
  5. Upon logout we will remove Bob’s session cookie.

If you don’t want to expose Username inside cookie then you can store some other unique value for the user.

Required Imports
Application Secret Key

To make use of flask session and message flashing we set application secret key. It is of paramount importance to configure strong secret key for the security of the application. Flask will make use of this key to sign session cookies.

Routes

We will build following four flask routes for signup, login, user home page and logout.

This route will allow new user to register an account. Note that how it’s making use of generate_password_hash to store hashed password into database. It will existing username in database and flash message. Once user is created it will redirect user to login page.

This route will serve login page for User. It will accept Username and Password in plaintext. Using check_password_hash it will check plaintext password with hashed value stored in database. If hash value matches then it will store session cookie with session[username] = True .

If user is successfully logged in then it should have session cookie for it’s username with value True . This route will check that value and show user it’s home page. It will abort request with 401 for the request with invalid cookie.

This route will get invoked when user logs out of the application. It will remove existing user session cookie.

Security Caveats

  • Always use HTTPS for deployment to serve cookies securely.
  • Test application locally with HTTPS before deployment.
  • Consider setting expiry date on cookie as flask does not set expiry date on the cookie by default. With flask defaults Session will be expired once browser is closed.
  • Never store any sensitive information inside cookie. In an event of compromise flask session cookie can be easily decoded.
  • Configure strong application secret before making use of flask’s session.
  • Use CSRF tokens on forms to prevent cross site request forgery.

Conclusion

We can build simple user authentication using flask’s session to gain more control on user’s session cookie. If you want to build complex system then you can consider using flask’s user management extensions. We have pushed working source code of simple login application on github. Feel free to use it in your projects. If you want to create single user login system without database then learn how HTTP Basic Access Authentication works and implement it in flask.

How to Authenticate Users in Flask with Flask-Login

Ondiek Elijah Ochieng

Ondiek Elijah Ochieng

How to Authenticate Users in Flask with Flask-Login

When you’re developing applications for the general public, it’s important to protect your users’ credentials and information. This means you need to know about code structure and how to implement various security measures.

In this article, we’ll walk through the steps to create a user authentication web app with Flask, a micro web framework. For authentication, we’ll use the Python library flask_login .

This app includes features such as form validations, account creation, and login/logout functionality for authenticated users.

Application Setup and Installation

You can find a comprehensive guide on setting up and installing the project on my GitHub repository.

Basic Application Structure

For this application, we’ll have a virtual environment in its own directory, as well as a folder containing the main application files. Here’s an overview of the app’s structure:

.
├── auth-app
│ ├── app.py
│ ├── database.db
│ ├── forms.py
│ ├── manage.py
│ ├── migrations
│ ├── models.py
│ ├── requirements.txt
│ ├── routes.py
│ ├── run
│ ├── static
│ └── templates
│ ├── auth.html
│ ├── base.html
│ └── index.html
└── venv

Application Factory

To kick it off, we’ll create an application factory function inside the app.py file and call it create_app . This is vital for any Flask app.

Also, we need to make some libraries available for use within our project, so we’ll import the following:

app.py

We imported Flask, SQLAlchemy to help our Python application communicate with a database, Bcrypt for password hashing, Migrate for database migrations, and several other methods from Flask-Login for session management.

To use flask_login, we’ll create an instance as shown above. We’ll do the same for SQLAlchemy, Migrate, and Bcrypt.

Instead of creating our Flask instance globally, we’ll do so within a function because doing so globally becomes difficult as the project grows.

The benefit of doing this within a function is that it allows for multiple application instances (also during testing). (Source: flask.palletsprojects.com)

Flask-Login also requires that we set a secret key in order to function. Also, you’ll notice that we have our initializations inside the application factory. We do this to avoid the extensions initially binding themselves to the application, as explained here.

Now that we’ve completed our basic application factory, it’s time to declare our User model. In the user table, we only need email, username, and password columns for this application.

models.py

We import db, an instance of SQLAlchemy, and a UserMixin subclass from Flask-Login in the above code snippet. Our work is simplified by using the UserMixin, which allows us to use methods such as is_authenticated(), is_active(), is_anonymous(), and get_id ().

If we don’t include the UserMixin in our User model, we’ll get errors like ‘User’ object has no attribute ‘is_active’ .

We currently have a User model, but we haven’t yet created the table. To do this, run python manage.py on your terminal inside your project directory—assuming you got the setup right, installed the packages in the requirements.txt file, and have an active virtual environment.

manage.py

The deploy function imports the create_app function from the app.py file, Flask-Migrate migration methods, and the User model. We then ensure that we are working within an application context, from which we can now call db.create all() , which will take care of our table creation.

We still need to set up the login and registration forms. First, we need to prepare the two Flask forms before rendering them on the template. The configuration for the forms is shown below. To keep this article neat and precise, I’ll omit the import lines. For the excluded import lines, see the GitHub repository.

forms.py

a). Registration form

In the above code snippet, we’re simply applying validations to the required fields imported from wtforms and assigning them to the form field variable names.

To speed up the validation process, we need to reduce the load and time required for server-side validation. To accomplish this, we add the above lines of code—email and username validation to our registration form class so that it is handled on the client side.

b). Login form

To make the form fields visible on the template, we must pass the form object to it via the route rendering that template. Now it’s time to define our application’s various routes. I’ll also leave out the import lines for this section.

routes.py

It is important to provide a user loader callback when using Flask-Login. This keeps the current user object loaded in that current session based on the stored id.

In the lines of code that follow, we simply define three routes for this application: home, login, and register. Notice how we create Flask form instances and then pass them along with the function return statement? We’ll modify these routes later to handle our login and registration needs. We’ll also add a logout route.

It’s time to write some HTML code. At this point, all we need is forms in the browser. NB: I’ll still leave out some lines of code to keep this article concise. The complete files are available on GitHub, but for the time being, let’s concentrate on the main areas of interest.

auth.html

The HTML template shown above serves as both our login and registration form. And I just used a few jinja templating tricks.

As you can see above, the form action is set to action=»<>» , where request.path retrieves the path from which the request originated and assigns it as the value for the form action. This eliminates the need to hard code the specific paths.

We also set a csrf token variable which allows the form validation to proceed while preventing session riding attacks.

It also handles flashed messages. Bootstrap 5 alerts make it simple to flash different messages based on their category. The following is an example of what that does.

error-msg

We simply print out the individual variable names from the form object to display the form fields. Here’s an example from the above snippet:

Another thing to consider is the use of if. else statements, such as in the following line of code:

By hiding some fields based on the request path, we can easily switch between the login and registration forms.

Remember the validation checks that we applied to the form fields? Also, we’d like to notify the user if they fail to provide the required input – so we’ll include some code for this. An example from the HTML form above is shown below.

The lines of code below will display the appropriate message to the user if any of the checks against the username are violated.

Here’s an example of what that would look like:

error-msg-2

How to modify routes.py

In Flask, adding new users to the database is simple. To complete today’s tutorial, we need to register, login, and logout users — that is, manage sessions.

a). Registration route

First and foremost, taking a closer look at the code snippet below for registering new users, we confirm that the form sending the data has passed all validation checks. So, if form.validate_on_submit():

If all of the checks pass, we get the values from the form fields, which are then passed to the User object, added to the database, and all of the changes are saved.

When the database is successfully updated with the new values, the user sees a success message. After that, the application redirects the user to the login page.

Any exceptions that may occur are caught and displayed to the user. This improves the user experience by displaying nicer alerts (and you can also modify the messages based on the exceptions).

It is not safe to store passwords in plain text because this increases the risk that user credentials will be compromised in the event of a breach.

The user password is hashed before being saved, and what is stored in the database is a highly encrypted combination of characters. We handled this with the help of Bcrypt. The hash is generated like this:

b). Login route

After passing validation, the User model is queried to see if a user exists with the email provided. If this fails it displays an error message. But if it’s validated, the second move is to compare the password issued with the hashed version of it. And if both match, access is granted and the user is redirected to the home page.

c). Logout route

The above route, which redirects to the login page, handles the termination of active sessions.

And that’s it! We’ve built our application with user authentication.

Thank you for reading. I hope you found this article useful. Continue to read, build, and best wishes. Don’t forget to follow me on Twitter as well @dev_elie.

Flask — делаем авторизацию на сайте

Admin 10.10.2020 , обновлено: 26.04.2021 Flask

Есть много способов построить авторизацию и административную часть (личный кабинет) на Flask. Некоторые предполагают самостоятельно все строить, другие имеют уже готовые концепции.

Перед тем как приступить к этой статье следует сделать всё что описано в статье делаем приложение на Flask в локальной среде.

Введение

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

Flask — это микрофреймворк, что предполагает создание проекта по модулям.

Ниже мы построим личный кабинет с авторизацией.

Установка расширений

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

Flask-Admin — с помощью этого расширения мы сможем создать личный кабинет на подобии того, что есть в Django.

Flask-WTF — расширение для Flask, являющееся оберткой WTForms, с помощью которого можно строить безопасные формы.

Также установим здесь email_validator, библиотеку для проверки эмейлов.

Flask-Security — разделение пользователей на роли.

Создаем модели для базы данных

Создаем файл:
app/models.py

Внутри которого пишем:

from datetime import datetime
from flask_login import UserMixin
from flask_security import RoleMixin
from app import db , login_manager
from werkzeug. security import generate_password_hash , check_password_hash

roles_users = db. Table (
‘roles_users’ ,
db. Column ( ‘user_id’ , db. Integer ( ) , db. ForeignKey ( ‘users.id’ ) ) ,
db. Column ( ‘role_id’ , db. Integer ( ) , db. ForeignKey ( ‘roles.id’ ) )
)

class Role ( db. Model , RoleMixin ) :
__tablename__ = ‘roles’
id = db. Column ( db. Integer ( ) , primary_key = True )
name = db. Column ( db. String ( 80 ) , unique = True )
description = db. Column ( db. String ( 255 ) )

def __str__ ( self ) :
return self . name

class User ( db. Model , UserMixin ) :
__tablename__ = ‘users’
id = db. Column ( db. Integer , unique = True , primary_key = True )
name = db. Column ( db. String )
username = db. Column ( db. String , unique = True )
email = db. Column ( db. String , unique = True )
password = db. Column ( db. String )
created_on = db. Column ( db. DateTime ( ) , default = datetime . utcnow )
updated_on = db. Column ( db. DateTime ( ) , default = datetime . utcnow , onupdate = datetime . utcnow )
# Нужен для security!
active = db. Column ( db. Boolean ( ) )
# Для получения доступа к связанным объектам
roles = db. relationship ( ‘Role’ , secondary = roles_users , backref = db. backref ( ‘users’ , lazy = ‘dynamic’ ) )

# Flask — Login
@ property
def is_authenticated ( self ) :
return True

@ property
def is_active ( self ) :
return True

@ property
def is_anonymous ( self ) :
return False

# Flask-Security
def has_role ( self , *args ) :
return set ( args ) . issubset ( { role. name for role in self . roles } )

def get_id ( self ) :
return self . id

# Required for administrative interface
def __unicode__ ( self ) :
return self . username

def set_password ( self , password ) :
self . password = generate_password_hash ( password )

def check_password ( self , password ) :
return check_password_hash ( self . password , password )

# Отвечает за сессию пользователей. Запрещает доступ к роутам, перед которыми указано @login_required
@ login_manager. user_loader
def load_user ( user_id ) :
return db. session . query ( User ) . get ( user_id )

class Role — класс ролей связанная с таблицей roles.
class User — класс пользователей связанный с таблицей users.
roles_users = db.Table — создание связей между этими двумя таблицами, значение которых будет записываться в новую таблицу roles_users.

@property в виде is_authenticated, is_active, is_anonymous нужны будут для определения авторизованных, активных и анонимных пользователей.

@login_required — пригодится позже для разделения показа страниц на авторизованных и не авторизованных пользователей.

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

Запускаем миграцию этих таблиц:

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

Добавляем модуль admin

Создаём директорию admin в директории app со следующими файлами:

Содержимое файла __init__.py:

from app import db , app
from flask import url_for , redirect , request , abort
from app. models import User , Role

# flask-login
from flask_login import current_user
import flask_login as login

# flask-security
from flask_security import SQLAlchemyUserDatastore , Security

# flask-admin
import flask_admin
from flask_admin import helpers , expose
from flask_admin. contrib import sqla

# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore ( db , User , Role )
security = Security ( app , user_datastore )

# Create customized model view class
class MyModelView ( sqla. ModelView ) :

def is_accessible ( self ) :
return ( current_user. is_active and
current_user. is_authenticated and
current_user. has_role ( ‘admin’ )
)

def _handle_view ( self , name , **kwargs ) :
"""
Override builtin _handle_view in order to redirect users when a view is not accessible.
"""
if not self . is_accessible ( ) :
if current_user. is_authenticated :
# permission denied
abort ( 403 )
else :
return redirect ( url_for ( ‘security.login’ , next = request. url ) )

# Переадресация страниц (используется в шаблонах)
class MyAdminIndexView ( flask_admin. AdminIndexView ) :
@ expose ( ‘/’ )
def index ( self ) :
if not current_user. is_authenticated :
return redirect ( url_for ( ‘.login_page’ ) )
return super ( MyAdminIndexView , self ) . index ( )

@ expose ( ‘/login/’ , methods = ( ‘GET’ , ‘POST’ ) )
def login_page ( self ) :
if current_user. is_authenticated :
return redirect ( url_for ( ‘.index’ ) )
return super ( MyAdminIndexView , self ) . index ( )

@ expose ( ‘/logout/’ )
def logout_page ( self ) :
login. logout_user ( )
return redirect ( url_for ( ‘.index’ ) )

@ expose ( ‘/reset/’ )
def reset_page ( self ) :
return redirect ( url_for ( ‘.index’ ) )

# Create admin
admin = flask_admin. Admin ( app , index_view = MyAdminIndexView ( ) , base_template = ‘admin/master-extended.html’ )

# Add view
admin. add_view ( MyModelView ( User , db. session ) )

# define a context processor for merging flask-admin’s template context into the
# flask-security views.
@ security. context_processor
def security_context_processor ( ) :
return dict (
admin_base_template = admin. base_template ,
admin_view = admin. index_view ,
h = helpers ,
get_url = url_for
)

Создаем шаблоны для административной части

templates/admin

Создаем внутри директории templates директорию admin. В этой директории добавляем файлы.

master-extended.html

Файлом master-extended.html мы расширяем админ панель. В конкретно данном случае добавляем кнопку выхода на админ панель справа:

{ % extends ‘admin/base.html’ % }
{ % block access_control % }

index.html

Файл index.html у нас выступит формой входа:

Содержимое файла может быть таким:

< div >
{ % if current_user. is_authenticated % }
< div >
< h2 > Logged in User details < /h2 >
< 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 >

< h2 > Основные ваши настройки < /h2 >
< p class = "lead" > Вы можете: < /p >
< p >< a href = "/admin/change/" > Изменить пароль < /a >< /p >
< /div >

templates/security

Когда было установлено расширение Flask-Security в директории templates появилась директория security, а в ней следующие файлы:

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

Шаблоны, которые они расширяют находятся здесь:

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

Config

Для того, чтобы все работало нам нужно добавить данные в файл конфига config-extended. К этому моменты вы должны были ознакомиться с конфигурационными файлами Flask.

# URLs
SECURITY_URL_PREFIX = "/admin"
SECURITY_LOGIN_URL = "/login/"
SECURITY_LOGOUT_URL = "/logout/"
SECURITY_POST_LOGIN_VIEW = "/admin/"
SECURITY_POST_LOGOUT_VIEW = "/admin/"
SECURITY_POST_REGISTER_VIEW = "/admin/"

# Включает регистрацию
SECURITY_REGISTERABLE = True
SECURITY_REGISTER_URL = "/register/"
SECURITY_SEND_REGISTER_EMAIL = False

# Включет сброс пароля
SECURITY_RECOVERABLE = True
SECURITY_RESET_URL = "/reset/"
SECURITY_SEND_PASSWORD_RESET_EMAIL = True

# Включает изменение пароля
SECURITY_CHANGEABLE = True
SECURITY_CHANGE_URL = "/change/"
SECURITY_SEND_PASSWORD_CHANGE_EMAIL = False

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

Blueprint

Последнее что нам нужно сделать для работы админки добавить регистрацию путей через Blueprint. Зачем нужен Blueprint и его настройка.

В файл app/__init__.py нужно добавить:

Может быть вы обратили внимание, что на скрине выше в модуле admin есть файл routes.py.

Если мы строим большой и расширяемый проект, то у нас в каждом модуле, где требуются роуты, будет свой файл routes.py с путями.

В файл routes.py надо добавить:

В этом файле на текущий момент больше ничего не нужно. Все наши роуты для админки прописаны в файле admin/__init__.py там где класс class MyAdminIndexView, но именно потому что они идут немного в другом формате и переплетены с функционалом. Чтобы все не усложнять мы оставим как есть, но практику применения роутов добавим.

Вход в админку

Теперь у нас есть админка. Заходим по адресу:

Регистрируемся на свой эмейл и заходим внутрь. Наша админка выглядит так (пока видны не все вкладки, мы дадим доступ к ним ниже):

Отдельные вкладки для неё мы можем добавлять в файле __init__.py. Например, вот как мы можем добавить новую вкладку для работы с таблицей UserSetting в базе данных (предварительно для неё должна быть создана модель в файле models.py, по инструкции выше):

Добавим роли для админки. Заходим к себе в БД. Как зайти в локальную ДБ через DataGrip или соединяемся удаленно с базой данных.

В таблице role добавим данные:

И добавим нашему пользователю роль администратора в таблице roles_users:

Читайте также

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

Комментарии к статье “ Flask — делаем авторизацию на сайте ” (4)

Добрый день, а где исходники шаблонов, которые мы расширяем base.html и master.html?

Да очень интересно. Не хватает фаилов base.html и master.html?

Исходники устанавливаются с расширениями:
pip install Flask-Login
pip install Flask-Admin

Мега-Учебник Flask, Часть 5: Вход пользователей

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

Цель данного руководства — разработать довольно функциональное приложение-микроблог, которое я за полным отсутствием оригинальности решил назвать microblog.

Краткое повторение

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

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

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

Конфигурация

Как и в предыдущих главах, мы начнём с настройки расширений, которые будем использовать. Для авторизации нам понадобятся два расширения — Flask-Login и Flask-OpenID. Настроим их следующим образом (файл app/__init__.py ):

Расширению Flask-OpenID нужно где-то хранить свои временные файлы, для этого при инициализации ему передаётся путь до папки tmp .

Функция представления авторизации

Давайте обновим нашу функцию представления (файл app/views.py ):

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

Отличий от предыдущей версии немного. Мы добавили новый декоратор для функции отображения. Благодаря oid.loginhandler Flask-OpenID теперь знает, что это — функция для авторизации.

g — это глобальный объект Flask, предназначенный для хранения и обмена данными во время жизни запроса. Именно в нём мы будем хранить данные о текущем пользователе. В верхней части тела функции мы проверяем значение g.user . Если пользователь уже авторизован, мы перенаправляем его на главную страницу. Бессмысленно пытаться еще раз проводить авторизацию в этом случае.

Функция url_for , которую мы использовали при вызове redirect , предоставляет возможность получения URL для переданного ей имени функции представления. Вы, конечно же, можете использовать redirect(‘/index’) , однако есть весьма веские причины поручить построение URL специально предназначенной для этого функции.

Мы также обновили код, обрабатывающий данные полученные из формы авторизации. Здесь мы делаем две вещи. Во-первых, мы сохраняем значение поля remember_me в сессии Flask (не путайте с db.session — сессией, предоставленной расширением Flask-SQLAlchemy). Как было сказано выше, объект flask.g может хранить данные только во время жизни запроса. В то время как flask.session является более сложным хранилищем. Данные, сохраненные в сессии, будут также доступны во время всех последующих запросов от одного клиента. Информация хранится до тех пор, пока не будет явно удалена. Такое поведение возможно благодаря тому, что Flask хранит отдельные сессии для каждого клиента.

Вызов oid.try_login запускает процесс авторизации с помощью Flask-OpenID. Эта функция принимает два аргумента: openid , полученный из веб-формы и список полей, которые мы хотели бы получить от провайдера OpenID. Так как наша модель User имеет атрибуты nickname и email , именно эти данные мы и будем запрашивать.

Аутентификация через OpenID проводится асинхронно. Если получен положительный ответ от провайдера, Flask-OpenID вызовет функцию, объявленную с помощью декоратора oid.after_login . В противном случае пользователь снова вернётся на страницу авторизации.

Обработка ответа от провайдера OpenID

Так выглядит реализация функции after_login (файл app/views.py ):

Аргумент resp , переданный функции after_login содержит в себе данные, полученные от провайдера OpenID.

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

После этого мы пытаемся получить значение remember_me из сессии Flask, это то самое значение, которое мы сохранили в функции представления login .

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

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

Для того, чтобы Flask-Login знал куда отправлять пользователей для авторизации, мы должны сообщить ему об этом при инициализации (файл app/__init__.py ):

Глобальный объект g.user

В функции представления login мы проверяли состояние g.user , для того, чтобы определить, не является ли текущий пользователь уже авторизованным. Чтобы это работало, мы используем событие Flask before_request . Все функции, объявленные с помощью декоратора before_request будут запущены непосредственно перед вызовом функции отображения каждый раз, когда получен запрос. Таким образом, вполне логичным будет устанавливать значение g.user именно здесь (файл app/views.py ):

Это всё, что нам нужно. Flask-Login предоставляет нам доступ к переменной current_user , мы просто копируем в g ссылку на это значение, для удобства дальнейшего использования. Теперь текущий пользователь будет доступен везде, даже внутри шаблонов.

Отображение главной страницы

В предыдущей главе мы использовали в функции index объекты-заглушки, так как у нас еще не было настоящих пользователей и постов. Теперь у нас есть пользователи, самое время это использовать:

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

Во-вторых, мы передаём в шаблон непосредственно объект g.user вместо заглушки, используемой ранее.

Самое время запустить приложение.

Когда вы перейдете по адресу http://localhost:5000 , вместо главной страницы вы увидите страницу для входа. Авторизация с помощью OpenID проходит с помощью URL , предоставляемого провайдером. Чтобы не вводить адрес вручную, можно использовать одну из ссылок под текстовым полем.

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

После этого вы окажетесь на главной странице, теперь уже в качестве авторизованного пользователя.

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

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

Мы реализовали вход, самое время добавить возможность выхода из системы. Это делается очень просто (файл app/views.py ):

Помимо этого нам необходимо добавить соответствующую ссылку в шаблон. Расположим её вверху страницы, рядом с другими навигационными ссылками (файл app/templates/base.html ):

Видите, насколько это просто! Нам всего лишь надо проверить содержимое g.user , и если текущий пользователь авторизован, добавить ссылку для выхода. Не забывайте, что вместо прямых адресов лучше использовать url_for в таких случаях..

Заключительные слова

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

Для экономии времени вы можете воспользоваться ссылкой и скачать код приложения, включающий в себя все изменения из данной статьи:
Скачать microblog-0.5.zip

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

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