Как я могу использовать два бэкенда аутентификации Django и предоставлять разный доступ в зависимости от того, какой из них используется?
У меня есть два различных класса пользователей для системы регистрации событий на основе Django. Назовем их "Регистрант" и "Сотрудник".
Эти два класса не являются взаимоисключающими, и я не вижу причин не использовать одну и ту же модель пользователя для обоих классов (с флагом для их различения).
Регистрант может войти в систему, подтвердив свою личность с помощью API третьей стороны, и затем зарегистрироваться на мероприятие.
Сотрудник имеет доступ к Django Admin и может управлять событиями. Я не доверяю стороннему API для достаточной аутентификации человека, имеющего доступ Staffer, поскольку, хотя он и запрашивает личную информацию для идентификации человека, он не запрашивает ничего такого надежного, как пароль. Поэтому я хочу, чтобы сотрудники вводили пароль вместо аутентификации через сторонний API.
<К сожалению, хотя я знаю, что могу использовать несколько бэкендов аутентификации, я застрял, пытаясь понять, как это сделать:
a) определить, какой бэкенд аутентификации использовать (например, использовать бэкенд аутентификации регистратора во фронтенде и бэкенд аутентификации сотрудника в админке) b) разрешить только пользователям, аутентифицированным через Staffer auth backend, доступ к Admin
Может ли кто-нибудь указать мне правильное направление?
Прошу прощения за отсутствие кода; я переделываю систему авторизации с нуля (потому что предыдущая версия была очень плохо взломана) и не знаю, с чего начать.
EDIT: Есть некоторая полезная информация на Django Multiple Authentication Backends Based On Status, но поскольку я хочу использовать одну модель User для обоих классов пользователей, и оба auth backends будут запрашивать различные типы учетных данных (например, один запрашивает пароль, другой нет), мне нужно больше подумать о том, как решить эту проблему.
если у меня была такая проблема, я использовал наследуемую модель для каждого из них, делая имя пользователя логином по умолчанию для персонала и email для регистратора, расширяя обе модели BaseUser.
для выбора бэкенда Auth я просто устанавливаю флажок или создаю разные урлы для входа.
Ответ на вопрос "определить, какой бэкенд аутентификации использовать" довольно прост, вам просто не нужно этого делать. Как указано в документации, когда вы вызываете authenticate()
функцию Django пробует каждую из AUTHENTICATION_BACKENDS
по очереди, пока одна из них либо не вернет пользователя, либо не вызовет PermissionDenied
исключение.
Кроме того, если вы посмотрите на код бэкенда по умолчанию [GitHub], если имя пользователя или пароль не переданы, он просто возвращает None
. Вам нужно будет реализовать свой бэкенд аналогичным образом, чтобы, если ожидаемые вами учетные данные не передаются, вы просто возвращали None
и позволяли другим (возможным) бэкендам справиться с этим.
Для "только разрешить пользователям, аутентифицированным через Staffer auth backend, доступ к Admin" вы можете определить сайт администратора по умолчанию и переопределить метод has_permission
:
from django.contrib import admin
from django.contrib.auth import BACKEND_SESSION_KEY
class MyAdminSite(admin.AdminSite):
def has_permission(self, request):
"""
Return True if the given HttpRequest has permission to view
*at least one* page in the admin site.
"""
try:
backend_path = request.session[BACKEND_SESSION_KEY]
staffer_backend = backend_path == "path.to.StafferBackend"
return request.user.is_active and request.user.is_staff and staffer_backend
except KeyError:
return False
А затем в apps.py
в одном из ваших приложений:
from django.contrib.admin.apps import AdminConfig
class MyAdminConfig(AdminConfig):
default_site = 'myproject.admin.MyAdminSite'
И наконец, в настройках замените 'django.contrib.admin'
на
INSTALLED_APPS = [
...
'myproject.apps.MyAdminConfig', # replaces 'django.contrib.admin'
...
]