Добавление аутентификации в ваше приложение с помощью Flask-Login | DigitalOcean

Введение

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

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

https://www.youtube.com/watch?v=bM50i7sKwwM

В этой статье мы затронем следующие вопросы:

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

Исходный код этого проекта доступен на GitHub.

Api wrappers

With respect to Python, API wrappers are essentially libraries/packages which can be installed using pip. These libraries help communicate with APIs in a syntactically cleaner way. Under the hood, the libraries still make use of requests and headers to make requests. However, the wrappers make your code look cleaner.

The Twilio API we discussed earlier has a wrapper. It can be installed using pip

pip install twilio

Let’s try to do the same thing we did in the previous section with Twilio

from twilio.rest import Client
from dotenv import load_dotenv
import os 


load_dotenv()
TWILIO_ACCOUNT_SID = os.environ.get("TWILIO_ACCOUNT_SID")
TWILIO_ACCOUNT_TOKEN = os.environ.get("TWILIO_ACCOUNT_TOKEN")
client = Client(TWILIO_ACCOUNT_SID , TWILIO_ACCOUNT_TOKEN)

calls = client.calls.list(limit=5)

for idx, record in enumerate(calls):
    print(f"{idx}. {record.duration}")

As you can see, the code is a few lines shorter and looks much cleaner.

Unfortunately, not all APIs have a wrapper. However, a lot of them do. Before a consumer, an API directly, try searching for a wrapper around it. This will make it significantly easier to work with the API.

Apis with keys

This is the most common form of authentication when consuming APIs. The API Key/Token is passed in as a header while making the request. We will be working with the Cat as a Service (CAAS) API. You can get a key here

In this article, we will be working with 5 different apis which use different types of authentication. we will be using python to consume the apis.

Not all APIs are as well documented as Twilio. This guide should help you work with APIs which are secured using Keys, BasicAuth, or OAuth2.

We will be working with the following APIS

You can find the source code here

Insecure apis

The Cat Facts API does not require any authentication and is fairly straightforward to work with. Let’s make a request to the following endpoint

Python requests анализ запроса

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

Если открыть .request, можно просмотреть PreparedRequest.

Проверка PreparedRequest открывает доступ ко всей информации о выполняемом запросе. Это может быть пейлоад, URL, заголовки, аутентификация и многое другое.

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

Python requests параметры запроса

Наиболее простым способом настроить запрос GET является передача значений через параметры строки запроса в URL. При использовании метода get(), данные передаются в params. Например, для того, чтобы посмотреть на библиотеку requests можно использовать Search API на GitHub.

Передавая словарь{‘q’: ‘requests language:python’} в параметр params, который является частью .get(), можно изменить ответ, что был получен при использовании Search API.

Можно передать параметры в get() в форме словаря, как было показано выше. Также можно использовать список кортежей.

Также можно передать значение в байтах.

Строки запроса полезны для уточнения параметров в запросах GET. Также можно настроить запросы при помощи добавления или изменения заголовков отправленных сообщений.

Python requests производительность приложений

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

Python установка библиотеки requests

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

Тем, кто для работы с пакетами Python, использует

Pipenv, необходимо использовать немного другую команду.

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

requests

можно полноценно использовать в приложении. Импорт

requests

производится следующим образом.

Таким образом, все подготовительные этапы для последующего использования

requests

завершены. Начинать

изучение requests

лучше всего с того, как сделать запрос

GET

Reading from .env files

Before moving on to the next sections, let’s look at how to read variables from a .env file. It’s highly recommended to store your credentials in a .env file to avoid them being exposed to others.

We will need to install the python-dotenv library.

pip install python-dotenv

Assume have a .env file with some random API Token

API_TOKEN = "SOME API TOKEN"

Let’s try reading the API Token in Python.

from dotenv import load_dotenv
import os 

load_dotenv()
API_TOKEN = os.environ.get("API_TOKEN")

The get function accepts a variable name stored in the .env file as an argument.

Requirements

All of the above with the exception of Bootstrap 4 can be installed directly from the requirements.txt file by running the following code on the command line pip install requirements.txt

N.B: The requirements.txt file is found on this projects github repo. The link will be given below. With regards to bootstrap 4,you can get the CDN from the official bootstrap website

Project Setup

There is no rule of thump when it comes to setting up your Django project but they are certain guidelines which developers are advised to follow. With that being said, my personal preference with regards to this can be found on my github repo.

We begin by creating our working directory and then create a virtual environment where we will install the project requirements.

Creating a virtual environment

conda create -n nameofvirtualenvironment

then, we activate our virtual environment with

activate nameofvirtualenvironemnt

Next

create a requirements.txt file in working directory and then copy and paste the contents of the same file from this project github repo,then run the following on the command line;

pip install requirements.txt

We mentioned in the very beginning, a basic understanding of Django was a prerequisite as such it’s assumed the readers already posses a basic know-how on to how setup their templates and static files.

Lets begin by creating a Django project called src by running the following command,

Resources

Github Repo

Table of contents

  • Insecure APIs
  • Reading values from.env files
  • APIs with Keys
  • APIs with Basic Auth
  • API Wrappers
  • The Session Object
  • APIs secured via OAuth2
  • Using the GitHub API (OAuth2)
  • Using the Genius API (OAuth2)

Some familiarity with the requests library is expected. If you need a refresher, you can refer to my previous article.

Using the genius api (oauth2)

Let’s take a look at another example. I’ll skip the part where we import the libraries and load the credentials.

Объект response получение ответа на запрос в python

Response представляет собой довольно мощный объект для анализа результатов запроса. В качестве примера будет использован предыдущий запрос, только на этот раз результат будет представлен в виде переменной. Таким образом, получится лучше изучить его атрибуты и особенности использования.

В данном примере при помощи get() захватывается определенное значение, что является частью объекта Response, и помещается в переменную под названием response. Теперь можно использовать переменную response для того, чтобы изучить данные, которые были получены в результате запроса GET.

Объект session в requests

До сих пор вы имели дело с requests API высокого уровня, такими как get() и post(). Эти функции являются абстракцией того, что происходит, когда вы делаете свои запросы. Они скрывают детали реализации, такие как управление соединениями, так что вам не нужно о них беспокоиться.

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

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

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

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

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

Получить содержимое страницы в requests

Зачастую ответ на запрос GET содержит весьма ценную информацию. Она находится в теле сообщения и называется пейлоад (payload). Используя атрибуты и методы библиотеки Response, можно получить пейлоад в различных форматах.

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

Использование .content обеспечивает доступ к чистым байтам ответного пейлоада, то есть к любым данным в теле запроса. Однако, зачастую требуется конвертировать полученную информацию в строку в кодировке UTF-8. response делает это при помощи .text.

Предварительные требования

Для этого обучающего модуля вам потребуется следующее:

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

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

Таймауты

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

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

В первом примере запрос истекает через 1 секунду. Во втором примере запрос истекает через 3,05 секунды.

Вы также можете передать кортеж. Это – таймаут соединения (время, за которое клиент может установить соединение с сервером), а второй – таймаут чтения (время ожидания ответа, как только ваш клиент установил соединение):

Если запрос устанавливает соединение в течение 2 секунд и получает данные в течение 5 секунд после установления соединения, то ответ будет возвращен, как это было раньше. Если время ожидания истекло, функция вызовет исключение Timeout.

Ваша программа может поймать исключениеTimeout и ответить соответственно.

Шаг 1 — установка пакетов

Для нашего проекта нам потребуется три основных проекта:

  • Flask
  • Flask-Login: для обработки пользовательских сеансов после аутентификации
  • Flask-SQLAlchemy: для представления пользовательской модели и интерфейса с нашей базой данных

Мы будем использовать SQLite, чтобы не устанавливать дополнительные зависимости для базы данных.

Для начала мы создадим каталог проекта:

  1. mkdirflask_auth_app

Затем нам нужно будет перейти в каталог проекта:

  1. cdflask_auth_app

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

  1. python3 -m venv auth
  2. sourceauth/bin/activate

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

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

  1. pip install flask flask-sqlalchemy flask-login

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

Шаг 10 — защита страниц

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

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

Шаг 2 — создание главного файла приложения

Для начала мы создадим каталог проекта:

  1. mkdir project

В первую очередь мы начнем работать над файлом __init__.py для нашего проекта:

  1. nano project/__init__.py

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

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

# init SQLAlchemy so we can use it later in our models
db = SQLAlchemy()defcreate_app():
    app = Flask(__name__)

    app.config['SECRET_KEY']='secret-key-goes-here'
    app.config['SQLALCHEMY_DATABASE_URI']='sqlite:///db.sqlite'

    db.init_app(app)# blueprint for auth routes in our appfrom.auth import auth as auth_blueprint
    app.register_blueprint(auth_blueprint)# blueprint for non-auth parts of appfrom.main import main as main_blueprint
    app.register_blueprint(main_blueprint)return app

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

Шаг 4 — создание шаблонов

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

  • index.html
  • profile.html
  • login.html
  • signup.html

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

Для начала создайте каталог templates в каталоге project:

  1. mkdir -p project/templates

Затем создайте base.html:

  1. nano project/templates/base.html

Добавьте следующий код в файл base.html:

project/templates/base.html

Шаг 5 — создание пользовательской модели

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

Модели, созданные в Flask-SQLAlchemy, представляются классами, которые преобразуются в таблицу в базе данных. Атрибуты этих классов превратятся в столбцы этих таблиц.

Давайте вместе создадим эту пользовательскую модель:

  1. nano project/models.py

Этот код создает пользовательскую модель со столбцами id, email, password и name:

Шаг 6 — настройка базы данных

Как указано в разделе «Предварительные требования», мы будем использовать базу данных SQLite. Мы можем создать базу данных SQLite самостоятельно, но сейчас используем для этого Flask-SQLAlchemy. Мы уже указали путь к базе данных в файле __init__.py, так что нам нужно просто указать Flask-SQLAlchemy создать базу данных на Python REPL.

Если вы остановите приложение и откроете Python REPL, мы сможем создать базу данных, используя метод create_all для объекта db. Убедитесь, что вы все еще находитесь в виртуальной среде и в каталоге flask_auth_app.

  1. from project import db, create_app, models
  2. db.create_all(app=create_app())# pass the create_app result so Flask-SQLAlchemy gets the configuration.

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

Теперь вы видите файл db.sqlite в каталоге проекта. В этой базе данных будет наша пользовательская таблица.

Шаг 7 — настройка функции авторизации

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

Для начала давайте добавим вторую функцию для обработки данных формы POST. В этой функции мы вначале соберем данные, которые были переданы пользователем.

Создайте функцию и добавьте в ее конец переадресацию. В результате после успешной регистрации пользователь будет переадресован на страницу входа.

Обновите файл auth.py, изменив строку import и реализовав signup_post:

Шаг 8 — тестирование метода регистрации

У нас готов метод регистрации, и теперь мы можем создать нового пользователя. Используйте форму для создания пользователя.

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

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

Вначале мы добавим элемент flash, выводимый до возврата на страницу регистрации.

Шаг 9 — добавление метода входа

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

Conclusion

I hope this article serves as a good guide to work with APIs in Python. Before consuming an API directly, always look for a wrapper. The 5 mins you spend looking for a wrapper might save you hours of headache.

Заключение

Изучение библиотеки Python requests является очень трудоемким процессом.

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

Похожее:  Как войти в личный кабинет Госуслуг зарегистрированному пользователю: инструкция

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

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