пятница, 23 мая 2014 г.

Кастомизация авторизации Django


Источник: https://docs.djangoproject.com/en/1.6/topics/auth/customizing/


Содержание
  1. Другие источники авторизации
    1. Указание бэкэндов авторизации
    2. Написание бэкэнда аутентификации
    3. Обращение к авторизации в собственных бэкэндах
      1. Авторизация анонимных пользователей
      2. Авторизация неактивных пользователей
      3. Обработка объектов разрешения
  2. Пользовательские разрешения
  3. Расширение существующей модели пользователя
  4. Подстановка собственной модели пользователя
    1. Ссылки на модель User
    2. Указание собственной модели User
    3. Расширение базовой модели User Django
    4. Пользовательские модели User и встроенные формы аутентификации
    5. Измененная модель User и django.contrib.admin
    6. Пользовательские модели User и модели Proxy



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

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

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

Вы можете расширить модель пользователя по-умолчанию, или замените ее полностью настроенной моделью.


Другие источники авторизации


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

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

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

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


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


За кадром, Django поддерживает список "адресов аутентификации", эта утилита проверяет наличие аутентификации. Когда кто-то вызывает django.contrib.auth.authenticate () - как описано в Как войти пользователю - Джанго пытается аутентификации во всех своих адресов аутентификации. Если первый метод проверки подлинности не удается, Джанго попробует второй, и так далее, пока все бэкенды не пытался это сделать.

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

По умолчанию, AUTHENTICATION_BACKENDS содержит это:

1
('django.contrib.auth.backends.ModelBackend',)


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

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

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


Новое в Django-1.6:
Если базовая программа вызывает исключение PermissionDenied, аутентификация сразу провалится. Django не будет проверять бэкенды, которые следуют за ним.


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


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

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

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

1
2
3
4
class MyBackend(object):
    def authenticate(self, username=None, password=None):
        # проверка username/password и возврат User
        ...

Но он также может проверить подлинность токена, вот так:

1
2
3
4
class MyBackend(object):
    def authenticate(self, token=None):
        # проверка токена и возврат User.
        ...

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

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

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from django.conf import settings
from django.contrib.auth.models import User, check_password

class SettingsBackend(object):
    """
    Аутентификация по настройкам ADMIN_LOGIN и ADMIN_PASSWORD.
    Использование логинного имени и хэша для пороля. Пример:
    ADMIN_LOGIN = 'admin'
    ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de'
    """

    def authenticate(self, 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:
                # Создать нового пользователя. Обратите внимание, 
                # что мы можем установить любой пароль, так как это 
                # не будет проверяться; здесь будет пароль из settings.py
                user = User(username=username, password='get from settings.py')
                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_group_permissions(), get_all_permissions(), has_perm(), и has_module_perms()), для любой бэкенд аутентификации, которая реализует эти функции.

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

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

1
2
3
4
5
6
7
class SettingsBackend(object):
    ...
    def has_perm(self, user_obj, perm, obj=None):
        if user_obj.username == settings.ADMIN_LOGIN:
            return True
        else:
            return False


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

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


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

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

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


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

Неактивным пользователь является тот, кто прошел проверку подлинности, но чей атрибут is_active установлен в False. Однако это не означает, что они не имеют права что-то делать. Например, они имеют право активировать свою учетную запись.

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

Не забудьте проверить атрибута пользователя is_active в ваших собственных методах разрешений бэкенда.


Обработка объектов разрешения

Фреймворк разрешений Django являются основанием для объекта разрешения, хотя его реализации нет в ядре. Это означает, что проверка на объект разрешения всегда будет возвращать значение False или пустой список (в зависимости от выполненной проверки). Бэкенд аутентификации получит ключевые слова в качестве параметров obj и user_obj для каждого объекта, связанные методы авторизации и может вернуть разрешение уровня объекта в зависимости от обстоятельств.


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


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

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

1
2
3
4
5
6
7
8
class Task(models.Model):
    ...
    class Meta:
        permissions = (
            ("view_task", "Can see available tasks"),
            ("change_task_status", "Can change the status of tasks"),
            ("close_task", "Can remove a task by setting its status as closed"),
        )

Единственное, что оно делает - создет лишние разрешения, когда вы запускаете manage.py syncdb. Ваш код отвечает за проверки значения этих разрешений, когда пользователь пытается получить доступ к функциональности, предоставляемой приложением (просмотр задач, изменение статуса задач, закрытие задач.) К приведенному выше примеру: проверки, если пользователь может просматривать задачи:

1
user.has_perm('app.view_task')



Расширение существующей модели пользователя


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

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

1
2
3
4
5
from django.contrib.auth.models import User

class Employee(models.Model):
    user = models.OneToOneField(User)
    department = models.CharField(max_length=100)

Предполагается существование Сотрудник Фред Смит, который имеет модели User и Employee, можно получить доступ к информации, связанной с использованием стандартных конвенций, связанных с моделями в Django:

1
2
>>> u = User.objects.get(username='fsmith')
>>> freds_department = u.employee.department

Чтобы добавить поля модели профиля на страницу администратора (админку), нужно определить InlineModelAdmin (для этого примера, мы будем использовать StackedInline) в admin.py вашего приложения и добавить его к классу UserAdmin которая зарегистрирована с классом User:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User

from my_user_profile_app.models import Employee

# Определение встроенного дескриптора администратора для модели Employee
# который действует как одиночный
class EmployeeInline(admin.StackedInline):
    model = Employee
    can_delete = False
    verbose_name_plural = 'employee'

# Определение нового User администратора
class UserAdmin(UserAdmin):
    inlines = (EmployeeInline, )

# Перерегистрация UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)

Эти модели профиля не были особенными - они всего лишь модели Django, которые имеют связь с моделью User один-к-одному. Таким образом, они не создаются автоматически при создании пользователя, но django.db.models.signals.post_save может быть использован для создания или обновления связанных моделей в зависимости от обстоятельств.

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

Устарело в Django 1.5:
Не рекомендуется начиная с версии 1.5: С введением моделей пользовательских USER, использование AUTH_PROFILE_MODULE определить единую модель профиля больше не поддерживается. См. примечания к выпуску Django 1.5 для получения дополнительной информации.

До 1.5 единая модель профиля может быть указана на веб-узле с заходящего AUTH_PROFILE_MODULE со строкой, состоящей из следующих элементов, разделенных точкой:
  1. Имя приложения (с учетом регистра), в которой определена модель профиля (другими словами, имя, который был принят в manage.py startapp для создания приложения).
  2. Название модели (без учета регистра) класс.
Например, если модель профиля - класс с именем UserProfile и был определен внутри приложения с именем accounts, соответствующая настройка будет выглядеть так:

1
AUTH_PROFILE_MODULE = 'accounts.UserProfile'

Когда модель профиля была определена и указана таким образом, каждый объект User будет иметь метод get_profile(), который возвращает экземпляр модели профиля пользователя, связанной с этим пользователем.

Метод get_profile() не создает профиль, если он не существует.


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


Новое в Django 1.5:

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

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

1
AUTH_USER_MODEL = 'myapp.MyUser'


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

Внимание!
Изменение AUTH_USER_MODEL имеет большое влияние на структуру вашей базы данных. Он изменяет таблицы, которые доступны, и это повлияет на состав внешних ключей и отношения многие-ко-многим. Если вы собираетесь установить AUTH_USER_MODEL, вы должны установить его перед первым запуском manage.py syncdb.

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


Ссылки на модель User


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

get_user_model()
Вместо ссылки на User напрямую, вы должны ссылаться на пользовательскую модель с использованием django.contrib.auth.get_user_model(). Данный метод возвращает текущий активный модель User - модель пользовательского User если она указана, или User иначе.

При определении внешнего ключа или отношения много-ко-многим к модели User, вы должны указать пользовательскую модель с помощью параметра AUTH_USER_MODEL. Например:

1
2
3
4
5
from django.conf import settings
from django.db import models

class Article(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL)


Указание собственной модели User


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

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


Django ожидает, что Ваша пользовательская модель User отвечает некоторым минимальным требованиям.
  1. Ваша модель должна иметь целый первичный ключ.
  2. Ваша модель должна иметь одно уникальное поле, которое может использоваться для целей идентификации. Это может быть имя пользователя, адрес электронной почты, или любой другой уникальный атрибут.
  3. Ваша модель должна обеспечивать способ решения пользователя в "короткий" и "длинного" ​​форме. Наиболее распространенным вариантом этого было бы использовать данное имя пользователя как "короткий" идентификатор, и полное имя пользователя как "длинный" идентификатор. Тем не менее, нет никаких ограничений на то, что бы вернуть эти два метода - если вы хотите, они могут вернуть точно такие же значения.
Самый простой способ построить совместимую пользовательскую модель User наследовать от AbstractBaseUser. AbstractBaseUser обеспечивает основы внедрения модели User, в том числе хэши паролей, разбивание на лексемы и сброс пароля. После этого вы должны предоставить некоторые ключевые детали реализации:

class models.CustomUser
USERNAME_FIELD
    Строка, описывающая имя поля модели User, которая используется в качестве уникального идентификатора. Это, как правило, какое-то имя пользователя, но он также может быть адресом электронной почты, или любой другой уникальный идентификатор. Поле должно быть уникальным (т.е. имеют unique=True набор в своем определении).

    В следующем примере, поле identifier используется в качестве идентифицирующего поля:

    1
    2
    3
    4
    class MyUser(AbstractBaseUser):
        identifier = models.CharField(max_length=40, unique=True)
        ...
        USERNAME_FIELD = 'identifier'
    

REQUIRED_FIELDS
    Список имен полей, которые будет предложено ввести при создании пользователя с помощью команды управления createsuperuser. Пользователю будет предложено ввести значение для каждого из этих полей. Он должен включать в себя любое поле, для которого по умолчанию имеет значение ЛОЖЬ или не определено и может включать в себя дополнительные поля, которые вы хотите ввести, когда пользователь создается в интерактивном режиме. Тем не менее, он не будет работать для ForeignKey полей. REQUIRED_FIELDS не имеет никакого эффекта в других частях Django, кроме как создание пользователя администратора.

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

    1
    2
    3
    4
    5
    6
    class MyUser(AbstractBaseUser):
        ...
        date_of_birth = models.DateField()
        height = models.FloatField()
        ...
        REQUIRED_FIELDS = ['date_of_birth', 'height']
    

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

is_active
    Логический атрибут, который указывает пользователю, считается ли он "активным". Этот атрибут предоставляется в качестве атрибута AbstractBaseUser по умолчанию в значении True. Как вы решите реализовать - будет зависеть от деталей выбранные вами бэкенда аутонтификации. За подробностями см. документацию по атрибуту is_active встроенной модели пользователя.

get_full_name()
    Более формальный идентификатор для пользователя. Чаще интерпретируется как полное имя пользователя, но это может быть любая строка, которая идентифицирует пользователя.

get_short_name()
    Короткий, неформальный идентификатор пользователя. Чаще интерпретируется как первым имя пользователя, но это может быть любая строка, идентифицирующая пользователя в неформальной обстановке. Он также может возвращать то же значение, что и django.contrib.auth.models.User.get_full_name().

Следующие методы доступны для любого подкласса AbstractBaseUser:

class models.AbstractBaseUser
get_username()
    Возвращает значение поля, назначенного USERNAME_FIELD.

is_anonymous()
    Всегда возвращает значение False. Это способ дифференцироваться от объектов AnonymousUser. Как правило, вы должны предпочесть использование is_authenticated() для этого метода.

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

set_password(raw_password)
    Устанавливает пароль пользователя на введенную сырую строку, заботясь о хэширования паролей. Не сохраняется объектом AbstractBaseUser.

    Когда raw_password не указывается, то пароль будет установлен в непригодном для использования пароля, как будто были использованы set_unusable_password().
      Изменено в Django 1.6:
      В Django 1.4 и 1.5, пустая строка так же непреднамеренно сохранялась как unsable пароль.

check_password(raw_password)
    Возвращает True, если данная сырая строка является правильным паролем для пользователя. (Об этом заботится сравнение хэшированных паролей)
      Изменено в Django 1.6:
      В Django 1.4 и 1.5, пустая строка была непреднамеренно считается непригодным пароль, в результате чего этот метод возвращения значение False для такого пароль.

set_unusable_password()
    Отмечает пользователя, как не имеющиго набора паролей. Это не то же самое, что имеющий пустое строку для ввода пароля. check_password() для этого пользователя никогда не вернется True. Не сохраняет объект AbstractBaseUser.

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

has_usable_password()
    Возвращает False, если set_unusable_password() был вызван для этого пользователя.

Вы должны также определить пользовательский менеджер для вашей модели пользователя. Если ваша модель User определяет username, email, is_staff, is_active, is_superuser, last_login и date_joined такие же, как и по умолчанию пользователя Джанго, вы можете просто установить UserManager Джанго; Однако, если ваша модель User определяет различные поля, вам нужно будет определить пользовательский менеджер, который расширяет BaseUserManager обеспечивая два дополнительных метода:

class models.CustomUserManager
create_user(*username_field*, password=None, **other_fields)
    Прототип create_user() должен принимать поле username, а также все необходимые поля в качестве аргументов. Например, если ваша модель пользователь использует электронную почту как поле имени пользователя, и имеет date_of_birth как обязательное поле, то create_user должен быть определен так:

    1
    2
    3
    def create_user(self, email, date_of_birth, password=None):
        # создать пользователя здесь
        ...
    

create_superuser(*username_field*, password, **other_fields)
    Прототип create_superuser() должен принимать поле username, а также все необходимые поля в качестве аргументов. Например, если ваша модель пользователь использует электронную почту как поле имени пользователя, и имеет date_of_birth как обязательное поле, то create_superuser должен быть определен как:

    1
    2
    3
    def create_superuser(self, email, date_of_birth, password):
        # создать суперпользователя здесь
        ...
    

    В отличие от create_user(), create_superuser() должен требовать от пользователя ввести пароль.

BaseUserManager предоставляет следующие вспомогательные методы:

class models.BaseUserManager
normalize_email(email)
    Метод класса, который нормализует доменную часть адреса электронной почты в нижний регистр.

get_by_natural_key(username)
    Получает экземпляр пользователя, используя содержимое поля, присвоенного USERNAME_FIELD.

make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')
    Возвращает случайное пароль заданной длины и случайную строку из разрешенных символов. Обратите внимание, что значение по умолчанию allowed_chars нет букв, которые могут ввести пользователей в заблуждение, в том числе:
      • i, l, I, и 1 (строчная буква i, строчная буква L, прописная буква i, и номер один)
      • o, O, и 0 (строчная буква о, прописная буква О, и ноль)


Расширение базовой модели User Django


Если вы полностью довольны моделью User Джанго, и вы просто хотите добавить некоторую дополнительную информацию о профиле, вы можете использовать подкласс django.contrib.auth.models.AbstractUser и добавить свои пользовательские поля профиля. Этот класс обеспечивает полное осуществление пользователя по умолчанию в качестве абстрактной модели.


Пользовательские модели User и встроенные формы аутентификации


Как вы можете ожидать, встроенные формы и представления Django, можно сделать определенные предположения о модели пользователя, что они работают вместе.

Если ваша модель User не следует тем же предположениям, то может понадобиться определить замену форме, и передать эту форму в качестве части конфигурации views аутентификации.
  • UserCreationForm
    Зависит от модели пользователя. Должен быть переписан для любых измененных моделей User.
  • UserChangeForm
    Зависит от модели пользователя. Должен быть переписан для любых измененных моделей User.
  • AuthenticationForm
    Работает с любым подклассом AbstractBaseUser, и будет адаптироваться к использованию поля, определенного в USERNAME_FIELD.
  • PasswordResetForm
    Предполагается, что модель пользователя имеет целый первичный ключ, имеет поле с именем электронной почты, которое может использоваться для идентификации пользователя и логическое поле с именем is_active чтобы предотвратить сброс паролей для неактивных пользователей.
  • SetPasswordForm
    Работает с любым подклассом AbstractBaseUser
  • PasswordChangeForm
    Работает с любым подклассом AbstractBaseUser
  • AdminPasswordChangeForm
    Работает с любым подклассом AbstractBaseUser

Измененная модель User и django.contrib.admin


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

PermissionsMixin предоставляет следующие методы и атрибуты:
class models.PermissionsMixin
is_superuser
    Логическое. Обозначает, что данный пользователь имеет все права без явного их присвоения.

get_group_permissions(obj=None)
    Возвращает набор строк разрешений, которые пользователь имеет через его/ее группы.

    Если объект передается, то возвращает права доступа для групп для конкретно данного объекта.

get_all_permissions(obj=None)
    Возвращает набор строк разрешений, которые пользователь имеет как через группы, так и через разрешения пользователя.

    Если объект передается, то возвращает права доступа для групп для конкретно данного объекта.

has_perm(perm,obj=None)
    Возвращает True, если пользователь имеет указанное разрешение, где perm в формате "." (см. разрешения). Если пользователь неактивен, этот метод всегда будет возвращать False.

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

has_perms(perm_list,obj=None)
    Возвращает True, если пользователь имеет каждое из указанных разрешений, где каждый perm в формате "." (см. разрешения). Если пользователь неактивен, этот метод всегда будет возвращать False.

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

has_module_perms(package_name)
    Возвращает True, если пользователь имеет все разрешения в данном пакете (метка приложения Django). Если пользователь неактивен, этот метод всегда будет возвращать False.


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



Пользовательские модели User и модели Proxy


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

Если ваш проект использует модель Proxy, необходимо либо изменить прокси под расширенную модель User, которая используется в настоящее время в вашем проекте, или объединить поведение вашей прокси в ваш подкласс User.

Полные примеры


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

Этот код все будут жить в файле models.py для приложения пользовательский аутентификации:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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):
        """
        Создание и сохранение пользователя с данной 
        электронной почтой, датой рождения и паролем.
        """
        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):
        """
        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 get_full_name(self):
        # The user is identified by their email address
        return self.email

    def get_short_name(self):
        # The user is identified by their email address
        return self.email

    # On Python 3: def __str__(self):
    def __unicode__(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

Комментариев нет:

Отправить комментарий