Настройка аутентификации в Django ¶
Аутентификация, поставляемая с Django, достаточно хороша для большинства распространенных случаев, но у вас могут быть потребности, которые не удовлетворяются стандартными настройками по умолчанию. Настройка аутентификации в ваших проектах требует понимания того, какие точки предоставленной системы можно расширять или заменять. Этот документ предоставляет подробную информацию о том, как можно настроить систему аутентификации.
Бэкенды аутентификации предоставляют расширяемую систему, когда имя пользователя и пароль, хранящиеся в модели пользователя, необходимо аутентифицировать в другой службе, отличной от службы по умолчанию Django.
Вы можете предоставить своим моделям специальные разрешения, которые можно проверить через систему авторизации Django.
Вы можете расширитьUser
модель по умолчанию или
заменить полностью настроенную модель.
Другие источники аутентификации ¶
Бывают случаи, когда вам необходимо подключиться к другому источнику аутентификации, то есть к другому источнику имен пользователей и паролей или методов аутентификации.
Например, в вашей компании может уже быть установлен LDAP, в котором хранятся имя пользователя и пароль для каждого сотрудника. Если бы у пользователей были отдельные учетные записи в LDAP и приложениях на основе Django, это было бы проблемой как для сетевого администратора, так и для самих пользователей.
Итак, для обработки подобных ситуаций система аутентификации Django позволяет вам подключать другие источники аутентификации. Вы можете переопределить схему Django по умолчанию на основе базы данных или использовать систему по умолчанию в тандеме с другими системами.
См. Справку по бэкэнду аутентификации для получения информации о бэкэндах аутентификации, включенных в Django.
Указание бэкэндов аутентификации ¶
За кулисами Django поддерживает список «бэкэндов аутентификации», которые он проверяет на предмет аутентификации. Когда кто-то звонит
django.contrib.auth.authenticate()
- как описано в разделе «Как войти в систему» - Django пытается пройти аутентификацию во всех своих бэкэндах аутентификации. Если первый метод аутентификации не работает, Django пробует второй, и так далее, пока все бэкенды не будут выполнены.
Список используемых бэкэндов аутентификации указывается в
AUTHENTICATION_BACKENDS
настройке. Это должен быть список имен путей Python, указывающих на классы Python, которые знают, как аутентифицироваться. Эти классы могут быть где угодно на вашем пути Python.
По умолчанию AUTHENTICATION_BACKENDS
установлено:
['django.contrib.auth.backends.ModelBackend']
Это базовая программа аутентификации, которая проверяет базу данных пользователей Django и запрашивает встроенные разрешения. Он не обеспечивает защиту от атак грубой силы через какой-либо механизм ограничения скорости. Вы можете реализовать свой собственный механизм ограничения скорости в настраиваемом бэкэнде аутентификации или использовать механизмы, предоставляемые большинством веб-серверов.
Порядок имеет AUTHENTICATION_BACKENDS
значение, поэтому, если одно и то же имя пользователя и пароль действительны в нескольких бэкэндах, Django прекратит обработку при первом положительном совпадении.
Если серверная часть вызывает PermissionDenied
исключение, проверка подлинности немедленно завершится ошибкой. Django не будет проверять последующие серверные ВМ.
Примечание
После аутентификации пользователя Django сохраняет, какой бэкэнд использовался для аутентификации пользователя в сеансе пользователя, и повторно использует тот же бэкэнд в течение этого сеанса всякий раз, когда требуется доступ к текущему аутентифицированному пользователю. Это фактически означает, что источники аутентификации кэшируются для каждого сеанса, поэтому, если вы измените
AUTHENTICATION_BACKENDS
, вам нужно будет очистить данные сеанса, если вам нужно заставить пользователей повторно аутентифицироваться с использованием других методов. Самый простой способ сделать это - выполнить Session.objects.all().delete()
.
Написание бэкенда аутентификации ¶
Бэкэнд аутентификации - это класс, реализующий два обязательных метода:
get_user(user_id)
и , а также набор дополнительных методов авторизации, связанных с разрешениями .authenticate(request, **credentials)
get_user
Метод берет user_id
- что может быть имя пользователя, идентификатор базы данных или любой другой , но должен быть первичным ключом вашего пользовательского объекта - и возвращает объект пользователя или None
.
authenticate
Метод принимает request
аргумент и полномочия в качестве ключевых слов аргументов. В большинстве случаев это будет выглядеть так:
from django.contrib.auth.backends import BaseBackend
class MyBackend(BaseBackend):
def authenticate(self, request, username=None, password=None):
# Check the username/password and return a user.
...
Но он также может аутентифицировать токен, например:
from django.contrib.auth.backends import BaseBackend
class MyBackend(BaseBackend):
def authenticate(self, request, token=None):
# Check the token and return a user.
...
В любом случае authenticate()
следует проверить полученные учетные данные и вернуть объект пользователя, который соответствует этим учетным данным, если учетные данные действительны. Если они недействительны, он должен вернуться None
.
request
является HttpRequest
и может быть, None
если он не был предоставлен authenticate()
(который передает его в серверную часть).
Администратор Django тесно связан с объектом пользователя Django . Лучший способ справиться с этим - создать User
объект Django для каждого пользователя, который существует для вашей серверной части (например, в вашем каталоге LDAP, вашей внешней базе данных SQL и т. Д.). Вы можете либо написать сценарий, чтобы сделать это заранее, либо ваш authenticate
метод может сделать это при первом входе пользователя в систему.
Вот пример бэкэнда, который аутентифицируется по переменной имени пользователя и пароля, определенной в вашем settings.py
файле, и создает User
объект Django при первой аутентификации пользователя:
from django.conf import settings
from django.contrib.auth.backends import BaseBackend
from django.contrib.auth.hashers import check_password
from django.contrib.auth.models import User
class SettingsBackend(BaseBackend):
"""
Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD.
Use the login name and a hash of the password. For example:
ADMIN_LOGIN = 'admin'
ADMIN_PASSWORD = 'pbkdf2_sha256$30000$Vo0VlMnkR4Bk$qEvtdyZRWTcOsCnI/oQ7fVOu1XAURIZYoOZ3iq8Dr4M='
"""
def authenticate(self, request, username=None, password=None):
login_valid = (settings.ADMIN_LOGIN == username)
pwd_valid = check_password(password, settings.ADMIN_PASSWORD)
if login_valid and pwd_valid:
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
# Create a new user. There's no need to set a password
# because only the password from settings.py is checked.
user = User(username=username)
user.is_staff = True
user.is_superuser = True
user.save()
return user
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
Обработка авторизации в кастомных бэкэндах ¶
Пользовательские серверные части аутентификации могут предоставлять свои собственные разрешения.
Модель пользователя и его менеджер будет делегировать разрешение функции поиска ( get_user_permissions()
,
get_group_permissions()
,
get_all_permissions()
,
has_perm()
,
has_module_perms()
, и
with_perm()
) в любой серверной аутентификации , который реализует эти функции.
Разрешения, предоставленные пользователю, будут надмножеством всех разрешений, возвращаемых всеми бэкэндами. То есть Django предоставляет пользователю разрешение, которое предоставляет любой бэкэнд.
Если бэкэнд вызывает PermissionDenied
исключение в has_perm()
или
has_module_perms()
, авторизация немедленно завершится ошибкой, и Django не будет проверять последующие бэкэнды.
Бэкэнд может реализовать разрешения для волшебного администратора следующим образом:
from django.contrib.auth.backends import BaseBackend
class MagicAdminBackend(BaseBackend):
def has_perm(self, user_obj, perm, obj=None):
return user_obj.username == settings.ADMIN_LOGIN
Это дает полные разрешения пользователю, которому предоставлен доступ в приведенном выше примере. Обратите внимание, что в дополнение к тем же аргументам, которые передаются связанным
django.contrib.auth.models.User
функциям, все бэкэнд-функции аутентификации принимают в качестве аргумента объект пользователя, который может быть анонимным пользователем.
Полную реализацию авторизации можно найти в ModelBackend
классе django / contrib / auth / backends.py , который является бэкендом по умолчанию и auth_permission
большую часть времени запрашивает таблицу.
Авторизация для анонимных пользователей ¶
Анонимный пользователь - это пользователь, который не прошел проверку подлинности, т. Е. Не предоставил действительные данные проверки подлинности. Однако это не обязательно означает, что они не уполномочены что-либо делать. На самом базовом уровне большинство веб-сайтов разрешают анонимным пользователям просматривать большую часть сайта, а многие разрешают анонимную публикацию комментариев и т. Д.
В структуре разрешений Django нет места для хранения разрешений для анонимных пользователей. Однако пользовательский объект, переданный бэкэнду аутентификации, может быть django.contrib.auth.models.AnonymousUser
объектом, позволяющим бэкэнду определять настраиваемое поведение авторизации для анонимных пользователей. Это особенно полезно для авторов многоразовых приложений, которые могут делегировать все вопросы авторизации бэкэнду аутентификации, вместо того, чтобы требовать настройки, например, для управления анонимным доступом.
Авторизация для неактивных пользователей ¶
Неактивный пользователь - это тот, у которого в
is_active
поле установлено значение False
.
ModelBackend
И
RemoteUserBackend
движки аутентификации запрещает этим пользователям от аутентификации. Если в пользовательской модели пользователя нет is_active
поля, всем пользователям будет разрешена аутентификация.
Вы можете использовать AllowAllUsersModelBackend
или, AllowAllUsersRemoteUserBackend
если хотите разрешить аутентификацию неактивным пользователям.
Поддержка анонимных пользователей в системе разрешений позволяет реализовать сценарий, в котором анонимные пользователи имеют разрешения на какие-либо действия, а неактивные аутентифицированные пользователи - нет.
Не забудьте проверить is_active
атрибут пользователя в ваших собственных методах разрешения серверной части.
Обработка прав доступа к объектам ¶
Платформа разрешений Django имеет основу для разрешений на объекты, хотя в ядре ее реализации нет. Это означает, что проверка разрешений объекта всегда будет возвращать False
или пустой список (в зависимости от выполненной проверки). Серверная часть аутентификации получит параметры ключевого слова obj
и user_obj
для каждого метода авторизации, относящегося к объекту, и при необходимости может вернуть разрешение на уровне объекта.
Пользовательские разрешения ¶
Чтобы создать настраиваемые разрешения для данного объекта модели, используйте permissions
атрибут Meta модели .
В этом примере Task
модели создаются два настраиваемых разрешения, т. Е. Действия, которые пользователи могут или не могут выполнять с Task
экземплярами, специфичными для вашего приложения:
class Task(models.Model):
...
class Meta:
permissions = [
("change_task_status", "Can change the status of tasks"),
("close_task", "Can remove a task by setting its status as closed"),
]
Единственное, что это делает, - это создание этих дополнительных разрешений при запуске
(функция, создающая разрешения, подключена к сигналу). Ваш код отвечает за проверку значения этих разрешений, когда пользователь пытается получить доступ к функциям, предоставляемым приложением (изменение статуса задач или закрытие задач). Продолжая приведенный выше пример, следующая проверка может ли пользователь закрывать задачи. :manage.py migrate
post_migrate
user.has_perm('app.close_task')
Расширение существующей User
модели ¶
Есть два способа расширить User
модель по умолчанию
без замены вашей собственной модели. Если изменения, которые вам нужны, являются чисто поведенческими и не требуют каких-либо изменений в том, что хранится в базе данных, вы можете создать прокси-модель на основе User
. Это позволяет использовать любые функции, предлагаемые прокси-моделями, включая порядок по умолчанию, настраиваемые менеджеры или настраиваемые методы модели.
Если вы хотите сохранить информацию, относящуюся к User
, вы можете использовать
OneToOneField
для модели, содержащей поля для дополнительной информации. Эту модель «один к одному» часто называют моделью профиля, поскольку она может хранить информацию о пользователе сайта, не связанную с авторизацией. Например, вы можете создать модель Сотрудника:
from django.contrib.auth.models import User
class Employee(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
department = models.CharField(max_length=100)
Предполагая, что у существующего сотрудника Фреда Смита есть и модель пользователя, и модель сотрудника, вы можете получить доступ к соответствующей информации, используя стандартные соглашения о связанных моделях Django:
>>> u = User.objects.get(username='fsmith')
>>> freds_department = u.employee.department
Чтобы добавить поля модели профиля на страницу пользователя в админке, определите
InlineModelAdmin
(для этого примера мы будем использовать a
StackedInline
) в вашем приложении admin.py
и добавить его в UserAdmin
класс, который зарегистрирован с этим
User
классом:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User
from my_user_profile_app.models import Employee
# Define an inline admin descriptor for Employee model
# which acts a bit like a singleton
class EmployeeInline(admin.StackedInline):
model = Employee
can_delete = False
verbose_name_plural = 'employee'
# Define a new User admin
class UserAdmin(BaseUserAdmin):
inlines = (EmployeeInline,)
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Эти модели профилей ни в коем случае не являются особенными - это просто модели Django, которые имеют прямую связь с моделью пользователя. Таким образом, они не создаются автоматически при создании пользователя, но django.db.models.signals.post_save
могут использоваться для создания или обновления связанных моделей по мере необходимости.
Использование связанных моделей приводит к дополнительным запросам или объединениям для извлечения связанных данных. В зависимости от ваших потребностей, настраиваемая модель пользователя, включающая связанные поля, может быть вашим лучшим вариантом, однако существующие отношения с моделью пользователя по умолчанию в приложениях вашего проекта могут оправдать дополнительную нагрузку на базу данных.
Замена нестандартной User
модели ¶
Некоторые типы проектов могут иметь требования к аутентификации, для которых встроенная User
модель Django не всегда подходит. Например, на некоторых сайтах имеет смысл использовать адрес электронной почты в качестве идентификационного токена вместо имени пользователя.
Django позволяет вам переопределить модель пользователя по умолчанию, указав значение для AUTH_USER_MODEL
параметра, который ссылается на пользовательскую модель:
AUTH_USER_MODEL = 'myapp.MyUser'
Эта пара с точками описывает имя приложения Django (которое должно быть в вашем
INSTALLED_APPS
) и имя модели Django, которую вы хотите использовать в качестве своей пользовательской модели.
Использование пользовательской модели пользователя при запуске проекта ¶
Если вы начинаете новый проект, настоятельно рекомендуется настроить пользовательскую модель пользователя, даже если User
модели по умолчанию вам достаточно. Эта модель ведет себя идентично пользовательской модели по умолчанию, но вы сможете настроить ее в будущем, если возникнет необходимость:
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
pass
Не забудьте указать AUTH_USER_MODEL
на это. Сделайте это перед созданием каких-либо миграций или запуском в первый раз.manage.py migrate
Также зарегистрируйте модель в приложении admin.py
:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
admin.site.register(User, UserAdmin)
Переход к пользовательской модели в середине проекта ¶
Изменить AUTH_USER_MODEL
после того, как вы создали таблицы базы данных, значительно сложнее, поскольку это влияет, например, на внешние ключи и отношения «многие ко многим».
Это изменение не может быть выполнено автоматически и требует ручного исправления вашей схемы, перемещения данных из старой пользовательской таблицы и, возможно, ручного повторного применения некоторых миграций. См. # 25313 для схемы шагов.
Из-за ограничений функции динамической зависимости Django для заменяемых моделей модель, на которую ссылается, AUTH_USER_MODEL
должна быть создана при первой миграции своего приложения (обычно это называется 0001_initial
); в противном случае у вас возникнут проблемы с зависимостями.
Кроме того, вы можете столкнуться с ошибкой CircularDependencyError
при выполнении миграции, поскольку Django не сможет автоматически разорвать цикл зависимостей из-за динамической зависимости. Если вы видите эту ошибку, вам следует разорвать цикл, переместив модели, зависящие от вашей пользовательской модели, во вторую миграцию. (Вы можете попробовать создать две нормальные модели, которые связаны ForeignKey
друг с другом, и посмотреть, как makemigrations
разрешается эта круговая зависимость, если вы хотите увидеть, как это обычно делается.)
Многоразовые приложения и AUTH_USER_MODEL
¶
Многоразовые приложения не должны реализовывать настраиваемую модель пользователя. В проекте может использоваться много приложений, и два многоразовых приложения, реализующих настраиваемую модель пользователя, нельзя использовать вместе. Если вам нужно хранить в информации о пользователях в вашем приложении, используйте ForeignKey
или
OneToOneField
чтобы , settings.AUTH_USER_MODEL
как описано ниже.
Ссылка на User
модель ¶
Если вы ссылаетесь User
напрямую (например, ссылаясь на него во внешнем ключе), ваш код не будет работать в проектах, где AUTH_USER_MODEL
параметр был изменен на другую модель пользователя.
-
get_user_model
() ¶ Вместо того, чтобы ссылаться
User
напрямую, вы должны ссылаться на модель пользователя, используяdjango.contrib.auth.get_user_model()
. Этот метод вернет текущую активную модель пользователя - пользовательскую модель пользователя, если она указана, илиUser
иначе.Когда вы определяете внешний ключ или отношения «многие ко многим» для модели пользователя, вы должны указать настраиваемую модель с помощью
AUTH_USER_MODEL
параметра. Например:from django.conf import settings from django.db import models class Article(models.Model): author = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, )
При подключении к сигналам, отправляемым моделью пользователя, вы должны указать пользовательскую модель с помощью
AUTH_USER_MODEL
параметра. Например:from django.conf import settings from django.db.models.signals import post_save def post_save_receiver(sender, instance, created, **kwargs): pass post_save.connect(post_save_receiver, sender=settings.AUTH_USER_MODEL)
Вообще говоря, проще всего ссылаться на пользовательскую модель с
AUTH_USER_MODEL
настройкой в коде, который выполняется во время импорта, однако также можно вызвать,get_user_model()
пока Django импортирует модели, поэтому вы можете использовать .models.ForeignKey(get_user_model(), ...)
Если ваше приложение тестируется с несколькими пользовательскими моделями,
@override_settings(AUTH_USER_MODEL=...)
например , используя , и вы кэшируете результатget_user_model()
в переменной уровня модуля, вам может потребоваться прослушатьsetting_changed
сигнал, чтобы очистить кеш. Например:from django.apps import apps from django.contrib.auth import get_user_model from django.core.signals import setting_changed from django.dispatch import receiver @receiver(setting_changed) def user_model_swapped(**kwargs): if kwargs['setting'] == 'AUTH_USER_MODEL': apps.clear_cache() from myapp import some_module some_module.UserModel = get_user_model()
Указание пользовательской модели пользователя ¶
Когда вы начинаете свой проект с настраиваемой пользовательской модели, остановитесь и подумайте, является ли это правильным выбором для вашего проекта.
Хранение всей связанной с пользователем информации в одной модели устраняет необходимость в дополнительных или более сложных запросах к базе данных для получения связанных моделей. С другой стороны, может быть более подходящим хранить информацию о пользователе, относящуюся к конкретному приложению, в модели, которая имеет отношение к вашей пользовательской модели. Это позволяет каждому приложению указывать свои собственные требования к данным пользователя, не противореча и не нарушая предположений других приложений. Это также означает, что вы сохраните свою модель пользователя как можно более простой, сфокусированной на аутентификации и соблюдая минимальные требования, которые Django ожидает от пользовательских моделей.
Если вы используете бэкэнд аутентификации по умолчанию, ваша модель должна иметь одно уникальное поле, которое можно использовать для целей идентификации. Это может быть имя пользователя, адрес электронной почты или любой другой уникальный атрибут. Поле неуникального имени пользователя разрешено, если вы используете настраиваемый сервер аутентификации, который может его поддерживать.
Самый простой способ создать совместимую пользовательскую модель - это унаследовать от
AbstractBaseUser
.
AbstractBaseUser
предоставляет базовую реализацию модели пользователя, включая хешированные пароли и сброс паролей с помощью токенизации. Затем вы должны предоставить некоторые ключевые детали реализации:
-
класс
models.
CustomUser
¶ -
USERNAME_FIELD
¶ Строка, описывающая имя поля в модели пользователя, которое используется в качестве уникального идентификатора. Обычно это какое-то имя пользователя, но также может быть адрес электронной почты или любой другой уникальный идентификатор. Поле должно быть уникальным (т. Е.
unique=True
Задано в его определении), если только вы не используете настраиваемый сервер аутентификации, который может поддерживать неуникальные имена пользователей.В следующем примере поле
identifier
используется как поле идентификации:class MyUser(AbstractBaseUser): identifier = models.CharField(max_length=40, unique=True) ... USERNAME_FIELD = 'identifier'
-
EMAIL_FIELD
¶ Строка, описывающая имя поля электронной почты в
User
модели. Это значение возвращаетсяget_email_field_name()
.
-
REQUIRED_FIELDS
¶ Список имен полей, которые будут запрошены при создании пользователя с помощью команды
createsuperuser
управления. Пользователю будет предложено ввести значение для каждого из этих полей. Она должна включать в себя любое поле , для которогоblank
являетсяFalse
или неопределенным и может включать в себя дополнительные поля , которые вы хотите запрашиваться при создании пользователя в интерактивном режиме .REQUIRED_FIELDS
не влияет на другие части Django, например на создание пользователя в админке.Например, вот частичное определение модели пользователя, которое определяет два обязательных поля - дату рождения и рост:
class MyUser(AbstractBaseUser): ... date_of_birth = models.DateField() height = models.FloatField() ... REQUIRED_FIELDS = ['date_of_birth', 'height']
Примечание
REQUIRED_FIELDS
должен содержать все обязательные поля в вашей пользовательской модели, но не должен содержатьUSERNAME_FIELD
или, такpassword
как эти поля всегда будут запрашиваться.
-
is_active
¶ Логический атрибут, указывающий, считается ли пользователь «активным». Этот атрибут предоставляется как атрибут по
AbstractBaseUser
умолчаниюTrue
. То, как вы решите реализовать это, будет зависеть от деталей выбранных вами бэкэндов аутентификации. Подробности см. В документации .is_active attribute on the built-in user model
-
get_full_name
() ¶ По желанию. Более длинный формальный идентификатор пользователя, например полное имя. Если реализовано, это отображается рядом с именем пользователя в истории объекта в
django.contrib.admin
.
-
get_short_name
() ¶ По желанию. Короткий неформальный идентификатор пользователя, например его имя. Если реализовано, это заменяет имя пользователя в приветствии пользователя в заголовке
django.contrib.admin
.
Импорт
AbstractBaseUser
AbstractBaseUser
иBaseUserManager
импортируются из файлов,django.contrib.auth.base_user
поэтому их можно импортировать без включенияdjango.contrib.auth
вINSTALLED_APPS
.-
Следующие атрибуты и методы доступны в любом подклассе
AbstractBaseUser
:
-
класс
models.
AbstractBaseUser
¶ -
get_username
() ¶ Возвращает значение поля, назначенного
USERNAME_FIELD
.
-
clean
() ¶ Нормализует имя пользователя путем звонка
normalize_username()
. Если вы переопределите этот метод, обязательно вызовите,super()
чтобы сохранить нормализацию.
-
classmethod
get_email_field_name
() ¶ Возвращает имя поля электронной почты, указанное
EMAIL_FIELD
атрибутом. По умолчанию,'email'
еслиEMAIL_FIELD
не указано.
-
classmethod
normalize_username
( имя пользователя ) ¶ Применяет нормализацию NFKC Unicode к именам пользователей, чтобы визуально идентичные символы с разными кодовыми точками Unicode считались идентичными.
-
is_authenticated
¶ Атрибут только для чтения, который есть всегда
True
(а неAnonymousUser.is_authenticated
всегдаFalse
). Это способ узнать, прошел ли пользователь аутентификацию. Это не подразумевает каких-либо разрешений и не проверяет, активен ли пользователь или имеет ли действующий сеанс. Несмотря на то, что обычно вы проверяете этот атрибут,request.user
чтобы узнать, был ли он заполненAuthenticationMiddleware
(представляющим текущего пользователя, вошедшего в систему), вы должны знать, что этот атрибут предназначенTrue
для любогоUser
экземпляра.
-
is_anonymous
¶ Атрибут только для чтения, который есть всегда
False
. Это способ различения объектовUser
иAnonymousUser
объектов. Как правило, вы должны предпочесть использованиеis_authenticated
этого атрибута.
-
set_password
( raw_password ) ¶ Устанавливает пароль пользователя на заданную необработанную строку, заботясь о хешировании пароля. Не сохраняет
AbstractBaseUser
объект.Когда raw_password равен
None
, будет установлен непригодный для использования пароль, как если бы онset_unusable_password()
был использован.
-
check_password
( raw_password ) ¶ Возвращает,
True
если данная необработанная строка является правильным паролем для пользователя. (Это позаботится о хешировании пароля при сравнении.)
-
set_unusable_password
() ¶ Помечает пользователя как не имеющего установленного пароля. Это не то же самое, что наличие пустой строки для пароля.
check_password()
ибо этот пользователь никогда не вернетсяTrue
. Не сохраняетAbstractBaseUser
объект.Это может вам понадобиться, если аутентификация для вашего приложения выполняется с использованием существующего внешнего источника, такого как каталог LDAP.
-
has_usable_password
() ¶ Возвращает,
False
еслиset_unusable_password()
был вызван для этого пользователя.
-
get_session_auth_hash
() ¶ Возвращает HMAC поля пароля. Используется для аннулирования сеанса при смене пароля .
Изменено в Django 3.1:Алгоритм хеширования был изменен на SHA-256.
-
AbstractUser
подклассы AbstractBaseUser
:
-
класс
models.
AbstractUser
¶ -
clean
() ¶ Нормализует электронную почту, позвонив
BaseUserManager.normalize_email()
. Если вы переопределите этот метод, обязательно вызовите,super()
чтобы сохранить нормализацию.
-
Написание менеджера для кастомной модели пользователя ¶
Вы также должны определить настраиваемый менеджер для вашей пользовательской модели. Если ваша модель пользователя определяет username
, email
, is_staff
, is_active
, is_superuser
,
last_login
, и date_joined
поля так же , как пользователь Джанго по умолчанию, вы можете установить Джанго UserManager
; однако, если ваша пользовательская модель определяет разные поля, вам необходимо определить настраиваемый менеджер, который расширяется и BaseUserManager
предоставляет два дополнительных метода:
-
класс
models.
CustomUserManager
¶ -
create_user
( username_field , password = None , ** other_fields ) ¶ Прототип
create_user()
должен принимать поле имени пользователя и все обязательные поля в качестве аргументов. Например, если ваша модель пользователя используетemail
в качестве поля имени пользователя и имеетdate_of_birth
обязательное поле, то егоcreate_user
следует определить как:def create_user(self, email, date_of_birth, password=None): # create user here ...
-
create_superuser
( username_field , password = None , ** other_fields ) ¶ Прототип
create_superuser()
должен принимать поле имени пользователя и все обязательные поля в качестве аргументов. Например, если ваша модель пользователя используетemail
в качестве поля имени пользователя и имеетdate_of_birth
обязательное поле, то егоcreate_superuser
следует определить как:def create_superuser(self, email, date_of_birth, password=None): # create superuser here ...
-
Для ForeignKey
in USERNAME_FIELD
или
REQUIRED_FIELDS
эти методы получают значение
to_field
( primary_key
по умолчанию) существующего экземпляра.
BaseUserManager
предоставляет следующие служебные методы:
-
класс
models.
BaseUserManager
¶ -
classmethod
normalize_email
( электронная почта ) ¶ Нормализует адреса электронной почты за счет уменьшения доменной части адреса электронной почты.
-
get_by_natural_key
( имя пользователя ) ¶ Извлекает пользовательский экземпляр, используя содержимое поля, назначенного
USERNAME_FIELD
.
-
make_random_password
( длина = 10 , allowed_chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789' ) ¶ Возвращает случайный пароль заданной длины и заданной строки допустимых символов. Обратите внимание, что значение по умолчанию
allowed_chars
не содержит букв, которые могут ввести пользователя в заблуждение, в том числе:i
,l
,I
, И1
(строчные буквы я, строчная буква L, заглавная буква я, и номер один)o
,O
И0
(строчная буква О, заглавная буква О, и ноль)
-
classmethod
Расширение Django по умолчанию User
¶
Если вас полностью устраивает User
модель Django , но вы хотите добавить дополнительную информацию о профиле, вы можете django.contrib.auth.models.AbstractUser
создать подкласс и добавить свои настраиваемые поля профиля, хотя мы бы порекомендовали отдельную модель, как описано в примечании «Рекомендации по проектированию модели» в разделе « Указание» настраиваемая модель пользователя .
AbstractUser
предоставляет полную реализацию по умолчанию
User
в виде абстрактной модели .
Пользовательские пользователи и встроенные формы авторизации ¶
Встроенные формы и представления Django делают определенные предположения о пользовательской модели, с которой они работают.
Следующие формы совместимы с любым подклассом
AbstractBaseUser
:
AuthenticationForm
: Использует поле имени пользователя, указанное вUSERNAME_FIELD
.SetPasswordForm
PasswordChangeForm
AdminPasswordChangeForm
Следующие формы делают предположения о пользовательской модели и могут использоваться как есть, если эти предположения соблюдены:
PasswordResetForm
: Предполагается, что модель пользователя имеет поле, в котором хранится адрес электронной почты пользователя с именем, возвращаемымget_email_field_name()
(email
по умолчанию), которое может использоваться для идентификации пользователя, и логическое поле с именемis_active
для предотвращения сброса пароля для неактивных пользователей.
Наконец, следующие формы привязаны
User
и должны быть переписаны или расширены для работы с пользовательской моделью:
Если ваша пользовательская модель является подклассом AbstractUser
, вы можете расширить эти формы следующим образом:
from django.contrib.auth.forms import UserCreationForm
from myapp.models import CustomUser
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = CustomUser
fields = UserCreationForm.Meta.fields + ('custom_field',)
Пользовательские пользователи и ¶django.contrib.admin
Если вы хотите, чтобы ваша пользовательская модель также работала с администратором, ваша пользовательская модель должна определять некоторые дополнительные атрибуты и методы. Эти методы позволяют администратору контролировать доступ пользователя к контенту администратора:
-
класс
models.
CustomUser
-
is_staff
¶ Возвращает,
True
если пользователю разрешен доступ к сайту администратора.
-
is_active
¶ Возвращает,
True
если учетная запись пользователя в настоящее время активна.
-
has_perm(perm, obj=None):
Возвращает,
True
если у пользователя есть указанное разрешение. Еслиobj
предоставляется, необходимо проверить разрешение для конкретного экземпляра объекта.
-
has_module_perms(app_label):
Возвращает,
True
если у пользователя есть разрешение на доступ к моделям в данном приложении.
Вам также необходимо будет зарегистрировать свою пользовательскую модель у администратора. Если ваша пользовательская модель расширяется django.contrib.auth.models.AbstractUser
, вы можете использовать существующий django.contrib.auth.admin.UserAdmin
класс Django . Однако, если ваша модель пользователя расширяется
AbstractBaseUser
, вам необходимо определить собственный ModelAdmin
класс. Возможно создание подкласса по умолчанию
django.contrib.auth.admin.UserAdmin
; однако вам необходимо переопределить любое из определений, относящихся к полям django.contrib.auth.models.AbstractUser
, не относящимся к
вашему пользовательскому классу.
Примечание
Если вы используете настраиваемый класс, ModelAdmin
который является подклассом
django.contrib.auth.admin.UserAdmin
, вам необходимо добавить свои настраиваемые поля в fieldsets
(для полей, которые будут использоваться при редактировании пользователей) и в
add_fieldsets
(для полей, которые будут использоваться при создании пользователя). Например:
from django.contrib.auth.admin import UserAdmin
class CustomUserAdmin(UserAdmin):
...
fieldsets = UserAdmin.fieldsets + (
(None, {'fields': ('custom_field',)}),
)
add_fieldsets = UserAdmin.add_fieldsets + (
(None, {'fields': ('custom_field',)}),
)
См. Полный пример для получения более подробной информации.
Пользовательские пользователи и разрешения ¶
Чтобы упростить включение инфраструктуры разрешений Django в ваш собственный класс пользователя, Django предоставляет PermissionsMixin
. Это абстрактная модель, которую вы можете включить в иерархию классов для своей пользовательской модели, предоставляя вам все методы и поля базы данных, необходимые для поддержки модели разрешений Django.
PermissionsMixin
предоставляет следующие методы и атрибуты:
-
класс
models.
PermissionsMixin
¶ -
is_superuser
¶ Булево. Обозначает, что у этого пользователя есть все разрешения, без их явного назначения.
-
get_user_permissions
( obj = Нет ) ¶ Возвращает набор строк разрешений, которые есть у пользователя напрямую.
Если
obj
передается, возвращает только разрешения пользователя для этого конкретного объекта.
-
get_group_permissions
( obj = Нет ) ¶ Возвращает набор строк разрешений, которые есть у пользователя, через их группы.
Если
obj
передается, возвращает только разрешения группы для этого конкретного объекта.
-
get_all_permissions
( obj = Нет ) ¶ Возвращает набор строк разрешений, которые есть у пользователя, как для групп, так и для пользователей.
Если
obj
передается, возвращает только разрешения для этого конкретного объекта.
-
has_perm
( допустимо , obj = Нет ) ¶ Возвращает,
True
если у пользователя есть указанное разрешение, где указаноperm
в формате (см. Разрешения ). Если и оба , этот метод всегда возвращает ."<app label>.<permission codename>"
User.is_active
is_superuser
True
True
Если
obj
передается, этот метод проверяет не разрешение для модели, а для этого конкретного объекта.
-
has_perms
( perm_list , obj = Нет ) ¶ Возвращает,
True
если у пользователя есть все указанные разрешения, где каждое разрешение находится в формате . Если и оба , этот метод всегда возвращает ."<app label>.<permission codename>"
User.is_active
is_superuser
True
True
Если
obj
передается, этот метод проверяет разрешения не для модели, а для конкретного объекта.
-
has_module_perms
( имя_пакета ) ¶ Возвращает,
True
если у пользователя есть какие-либо разрешения в данном пакете (метка приложения Django). ЕслиUser.is_active
иis_superuser
обаTrue
, этот метод всегда возвращаетTrue
.
-
Пользовательские пользователи и модели прокси ¶
Одним из ограничений пользовательских моделей является то, что установка пользовательской модели нарушит любое расширение прокси-модели User
. Прокси-модели должны основываться на конкретном базовом классе; определяя пользовательскую модель пользователя, вы лишаете Django возможности надежно идентифицировать базовый класс.
Если ваш проект использует прокси-модели, вы должны либо изменить прокси, чтобы расширить пользовательскую модель, которая используется в вашем проекте, либо объединить поведение вашего прокси-сервера с вашим User
подклассом.
Полный пример ¶
Вот пример настраиваемого пользовательского приложения, совместимого с администратором. Эта модель пользователя использует адрес электронной почты в качестве имени пользователя и имеет требуемую дату рождения; он не обеспечивает проверки разрешений, кроме admin
флажка в учетной записи пользователя. Эта модель будет совместима со всеми встроенными формами авторизации и представлениями, за исключением форм создания пользователей. Этот пример показывает, как большинство компонентов работают вместе, но не предназначен для непосредственного копирования в проекты для производственного использования.
Весь этот код будет находиться в models.py
файле для пользовательского приложения аутентификации:
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
class MyUserManager(BaseUserManager):
def create_user(self, email, date_of_birth, password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
date_of_birth=date_of_birth,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, date_of_birth, password=None):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(
email,
password=password,
date_of_birth=date_of_birth,
)
user.is_admin = True
user.save(using=self._db)
return user
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
date_of_birth = models.DateField()
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['date_of_birth']
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
@property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
Затем, чтобы зарегистрировать эту пользовательскую модель у администратора Django, в admin.py
файле приложения потребуется следующий код :
from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.core.exceptions import ValidationError
from customauth.models import MyUser
class UserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = MyUser
fields = ('email', 'date_of_birth')
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserChangeForm(forms.ModelForm):
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
disabled password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = MyUser
fields = ('email', 'password', 'date_of_birth', 'is_active', 'is_admin')
class UserAdmin(BaseUserAdmin):
# The forms to add and change user instances
form = UserChangeForm
add_form = UserCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'date_of_birth', 'is_admin')
list_filter = ('is_admin',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('date_of_birth',)}),
('Permissions', {'fields': ('is_admin',)}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'date_of_birth', 'password1', 'password2'),
}),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
# Now register the new UserAdmin...
admin.site.register(MyUser, UserAdmin)
# ... and, since we're not using Django's built-in permissions,
# unregister the Group model from admin.
admin.site.unregister(Group)
Наконец, укажите пользовательскую модель в качестве модели пользователя по умолчанию для вашего проекта, используя AUTH_USER_MODEL
настройку в вашем settings.py
:
AUTH_USER_MODEL = 'customauth.MyUser'
В более старых версиях ReadOnlyPasswordHashField
не используется
disabled
по умолчанию и
UserChangeForm.clean_password()
требуется для возврата начального значения, независимо от того, что предоставил пользователь.