JWT Аутентификация в Django

Начало

Однажды мне пришлось заняться разработкой Web-приложения для корпоративного использования на Python Django. И самым первым вопросом, который пришлось решать — это прозрачная авторизация на сайте или

Single Sign-On (SSO)

Что такое jwt?

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

Api тесты

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

Single sign-on (sso) с рабочих станций windows

Еще раз повторюсь, что вся работа по настройке kerberos аутентификации в Linux проделана для того, чтобы иметь возможность входить на страницы портала опубликованного на Linux машине с использованием корпоративных аккаунтов, хранящихся в Active Directory, кроме того для упрощения жизни пользователям этот вход должен быть «прозрачным», без запроса пароля, что достигается иcпользованием технологии Single Sign-On (SSO), которая поддерживается в Windows 7 и выше и браузером Internet Explorer (и Mozilla Firefox).

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

Аутентификация пользователей

Мы будем использовать модуль Django-REST Framework JWT Python, который мы установили в начале этого руководства. Он добавляет поддержку JWT-аутентификации для приложений Django Rest Framework.

Но сначала давайте определим некоторые параметры конфигурации для наших токенов и как они сгенерированы в файле settings.py.

Выполняем несколько проверок работы kerberos на компьютере srv-app

Ранее, на нашем контроллере домена мы создали пользователя

srv-apache

с паролем

P@ssw0rd

Генерация keytab на контроллере домена windows

Сгенерировать keytab можно на контроллере домена

DC-1

при помощи команды ktpass.exe:

Дополнительные ресурсы

  1. Официальная документация django rest framework.
  2. Документация djoser.

Это конец этой долгой статьи. Я надеюсь, что с этой информацией вы также можете создать свой собственный RESTful API с помощью django.

Другие источники аутентификации¶

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

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

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

Смотрите authentication backend reference для получения информации о бэкендах аутентификации, включенных в Django.

Указание бэкендов аутентификации

За кулисами Django ведет список «бэкендов аутентификации», которые он проверяет на предмет аутентификации. Когда кто-то вызывает django.contrib.auth.authenticate() – как описано в How to log a user in – Django пытается пройти аутентификацию через все свои бэкенды аутентификации. Если первый метод аутентификации не работает, Django пробует второй, и так далее, пока не будут испробованы все бэкенды.

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

По умолчанию AUTHENTICATION_BACKENDS имеет значение:

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

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

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

Примечание

После того, как пользователь прошел аутентификацию, Django сохраняет, какой бэкенд был использован для аутентификации пользователя в его сессии, и повторно использует этот же бэкенд в течение всей сессии, когда требуется доступ к текущему аутентифицированному пользователю. Это фактически означает, что источники аутентификации кэшируются на основе каждой сессии, поэтому если вы измените AUTHENTICATION_BACKENDS, вам придется очистить данные сессии, если вам нужно заставить пользователей повторно аутентифицироваться с помощью других методов. Простой способ сделать это – выполнить Session.objects.all().delete().

Написание бэкенда аутентификации

Бэкэнд аутентификации – это класс, реализующий два обязательных метода: get_user(user_id) и authenticate(request,**credentials), а также набор необязательных методов, связанных с разрешениями authorization methods.

Метод get_user принимает user_id – который может быть именем пользователя, идентификатором базы данных или чем угодно, но должен быть первичным ключом вашего объекта user – и возвращает объект user или None.

Метод authenticate принимает аргумент request и учетные данные в качестве аргументов ключевых слов. В большинстве случаев это будет выглядеть следующим образом:

Но он также может аутентифицировать токен, например, так:

В любом случае, authenticate() должен проверить полученные учетные данные и вернуть объект пользователя, который соответствует этим учетным данным, если они действительны. Если они недействительны, он должен вернуть None.

request является HttpRequest и может быть None, если он не был предоставлен authenticate() (который передает его бэкенду).

Администратор Django тесно связан с Django User object. Лучший способ справиться с этим – создать объект Django User для каждого пользователя, который существует в вашем бэкенде (например, в вашем каталоге LDAP, вашей внешней базе данных SQL и т.д.) Вы можете либо написать скрипт, чтобы сделать это заранее, либо ваш метод authenticate может сделать это при первом входе пользователя.

Вот пример бэкенда, который аутентифицируется по переменной имени пользователя и пароля, определенной в вашем settings.py файле, и создает объект Django User при первой аутентификации пользователя:

Обработка авторизации в пользовательских бэкендах

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

Модель пользователя и ее менеджер делегируют функции поиска разрешений (get_user_permissions(), get_group_permissions(), get_all_permissions(), has_perm(), has_module_perms() и with_perm()) любому бэкенду аутентификации, который реализует эти функции.

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

Если бэкенд вызывает исключение PermissionDenied в has_perm() или has_module_perms(), авторизация будет немедленно провалена, и Django не будет проверять последующие бэкенды.

Бэкэнд может реализовать права доступа для волшебного администратора следующим образом:

Это дает полные полномочия пользователю, получившему доступ в приведенном выше примере. Обратите внимание, что в дополнение к тем же аргументам, которые передаются связанным функциям django.contrib.auth.models.User, все функции backend auth принимают в качестве аргумента объект user, который может быть анонимным пользователем.

Полную реализацию авторизации можно найти в классе ModelBackend в django/contrib/auth/backends.py, который является бэкендом по умолчанию и большую часть времени запрашивает таблицу auth_permission.

Авторизация для анонимных пользователей

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

Фреймворк разрешений Django не имеет места для хранения разрешений для анонимных пользователей. Однако объект user, передаваемый бэкенду аутентификации, может быть объектом django.contrib.auth.models.AnonymousUser, что позволяет бэкенду задавать пользовательское поведение авторизации для анонимных пользователей. Это особенно полезно для авторов повторно используемых приложений, которые могут делегировать все вопросы авторизации бэкенду auth, вместо того чтобы нуждаться в настройках, например, для контроля анонимного доступа.

Использование django-auth-ldap

Итак, нам нужно получить доступ к Active Directory при помощи протокола LDAP. К счастью отличным Django-приложением для этих целей является

. Установить его можно стандартно при помощи pip:

pip install django-auth-ldap


После этого придется удалить из settings.py добавленные в предыдущем разделе

MIDDLEWARE_CLASSES

, а именно

Использование django-remote-auth-ldap

Но, как оказалось, все гораздо проще. Велосипед уже придуман, и нам остается только им воспользоватся. Приложение

django-remote-auth-ldap

является небольшой надстройкой над

django_auth_ldap

и позволяет без лишних усилий авторизовать пользователя и загрузить его данные из AD во время авторизации.

Устанавливаем django-remote-auth-ldap стандартно (django-auth-ldap также необходим для работы этой надстройки):

pip install django-remote-auth-ldap

Далее, необходимо добавить в settings.py следующую настройку:

DRAL_CHECK_DOMAIN = False

Дело в том, что

django-remote-auth-ldap

Как работают веб-маркеры json

Когда пользователь успешно выполняет вход в систему с использованием своих учетных данных, создается пользовательский токен JSON и сохраняется в локальном хранилище. Всякий раз, когда пользователь хочет получить доступ к защищенному URL-адресу, токен отправляется в заголовке запроса. Затем сервер проверяет правильность JWT в заголовке авторизации, и если он валидный, пользователю будет разрешен доступ.

Содержимое заголовка обычно выглядит так:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsI

Ниже приведена диаграмма, показывающая этот процесс:

Концепция аутентификации и авторизации

Аутентификация – это процесс идентификации зарегистрированного пользователя, а авторизация – это процесс определения того, имеет ли определенный пользователь право доступа к веб-ресурсу.

Миграции

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

Создайте первоначальную миграцию для модели наших пользователей и выполните синхронизацию базы данных.

Настройка /etc/hosts, /etc/resolv.conf на srv-app, dns на dc-1

srv-app

добавляем в /etc/hosts:

Настройка базы данных

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

Создайте базу данных auth и назначьте пользователя.

Перейдите на учетную запись Postgres на вашем компьютере, набрав:

Зайдите в оболочку Postgres и создайте базу данных:

Создайте роль:

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

Установите пакет psycopg2, который позволит нам использовать настроенную нами базу данных:

Отредактируйте текущую базу данных SQLite и используйте базу данных Postgres.

Настройка параметров jwt

Чтобы использовать JWT, нам нужно настроить разрешения django-rest-framework для принятия JSON Web Tokens.

В файле settings.py добавьте следующие конфигурации:

Обновить аутентифицированного пользователя

Через запрос PUT

Обработка авторизации в пользовательских бэкендах¶

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

Получение и обновление пользователей

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

Получить все профили пользователей

Это будет через запрос GET.

Пользовательские пользователи и разрешения¶

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

PermissionsMixin предоставляет следующие методы и атрибуты:

Пользовательские разрешения¶

Чтобы создать пользовательские разрешения для данного объекта модели, используйте permissionsmodel Meta attribute.

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

Единственное, что это делает – создает эти дополнительные разрешения, когда вы выполняете manage.pymigrate (функция, создающая разрешения, подключена к сигналу post_migrate).

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

Права доступа

Разрешения определяют, должен ли запросу быть предоставлен или запрещен доступ. Django rest framework поставляется с несколькими. Я не буду вдаваться в подробности, поскольку их документация достаточно обширна. Однако давайте обратим наше внимание на класс разрешений IsOwnerProfileOrReadOnly.

Это реализация пользовательских разрешений. Мы инициализируем файл license.py и наполняем его следующим кодом:

Представления api

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

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

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

Некоторыми из этих представлений являются CreateAPIView, ListAPIView, ListCreateAPIView, RetrieveUpdateDestroyAPIView, и этот список можно продолжить.

Мы реализуем ListCreateAPIView и RetrieveUpdateDestroyAPIView.

Пример api

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

Сериализаторы

С базовыми настройками давайте перейдем к реализации API. Если вы новичок в django, сериализаторы позволяют преобразовывать сложные данные, такие как наборы запросов и экземпляры модели, в собственные типы данных Python, которые можно легко преобразовать в форматы, такие как JSON. Это называется сериализацией. Они также позволяют десериализацию после первой проверки данных входящего запроса.

В каталоге приложения мы запустим файл serializers.py и введем следующий код:

Создание новых пользователей

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

Создание проекта

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

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

Возвращаясь к первой части серии, мы установили несколько пакетов Python. Нам нужно добавить эти пакеты в файл settings.py проекта, чтобы использовать их в нашем проекте django.

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

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

Требования

Давайте начнем.

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

Активируйте виртуальную среду:

Создайте проект Django.

Указание пользовательской модели пользователя¶

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

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

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

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

Устанавливаем модули для работы с kerberos

    [root@srv-app ~]# yum install mod_auth_kerb     # Устанавливаем модуль для apache
    [root@srv-app ~]# yum install krb5-workstation    # Устанавливаем пакет для настройки и тестирования kerberos

Этап 1. настройка прозрачной аутентификации с использованием kerberos

Совершенно очевидно, что реализация принципа SSO в сети Windows AD возможно используя протокол Kerberos. Поэтому основной задачей первого этапа настройки будет установка Kerberos в среде Linux Apache и настройка связи с контроллером домена Windows AD.

Этап 2. авторизация пользователя в django

Итак, в результате работы проведенной на первом этапе, мы получили следующие результаты:

Однако, несмотря на то, что сервер Apache авторизовал нашего пользователя, для Django-приложения он все еще остается неизвестным и, соответственно, весь отлаженный в Django механизм аутентификации/авторизации пользователей и использования сессий остается пока незадействованным.

Заключение

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

Похожее:  ЧТО ТАКОЕ ЛИЧНЫЙ КАБИНЕТ БИЛАЙН

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

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