Разрешения
источник:
permissions.py
Разрешения
Аутентификация или идентификация сами по себе обычно недостаточны для получения доступа к информации или коду. Для этого субъект, запрашивающий доступ, должен иметь авторизацию.
Вместе с authentication и throttling разрешения определяют, следует ли предоставить или отказать в доступе запросу.
Проверка разрешений всегда выполняется в самом начале представления, до того, как будет разрешено выполнение любого другого кода. Проверки разрешений обычно используют информацию об аутентификации в свойствах request.user
и request.auth
, чтобы определить, должен ли входящий запрос быть разрешен.
Разрешения используются для предоставления или запрета доступа различных классов пользователей к различным частям API.
Самый простой стиль разрешения - разрешить доступ любому аутентифицированному пользователю и запретить доступ любому неаутентифицированному пользователю. Это соответствует классу IsAuthenticated
в DRF.
Несколько менее строгий стиль разрешения - разрешить полный доступ для аутентифицированных пользователей, но разрешить доступ только для чтения для неаутентифицированных пользователей. Это соответствует классу IsAuthenticatedOrReadOnly
в DRF.
Как определяются разрешения
Разрешения в DRF всегда определяются как список классов разрешений.
Перед запуском основной части представления проверяется каждое разрешение в списке. Если проверка какого-либо разрешения не удалась, будет вызвано исключение exceptions.PermissionDenied
или exceptions.NotAuthenticated
, и основное тело представления не будет запущено.
Если проверка разрешения не сработала, будет возвращен ответ "403 Forbidden" или "401 Unauthorized", в соответствии со следующими правилами:
Запрос был успешно аутентифицирован, но в разрешении было отказано. — Будет возвращен ответ HTTP 403 Forbidden.
Запрос не был успешно аутентифицирован, и класс аутентификации с наивысшим приоритетом не использует заголовки
WWW-Authenticate
. — Будет возвращен ответ HTTP 403 Forbidden.Запрос не был успешно аутентифицирован, и класс аутентификации с наивысшим приоритетом использует заголовки
WWW-Authenticate
. *— Будет возвращен ответ HTTP 401 Unauthorized с соответствующим заголовкомWWW-Authenticate
.
Разрешения на уровне объекта
Разрешения DRF также поддерживают разрешение на уровне объекта. Разрешения на уровне объекта используются для определения того, разрешено ли пользователю действовать с определенным объектом, который обычно является экземпляром модели.
Разрешения на уровне объекта запускаются общими представлениями DRF при вызове .get_object()
. Как и в случае с разрешениями на уровне представления, исключение exceptions.PermissionDenied
будет поднято, если пользователю не разрешено действовать с данным объектом.
Если вы пишете собственные представления и хотите обеспечить разрешения на уровне объекта, или если вы переопределите метод get_object
в общем представлении, то вам нужно будет явно вызвать метод .check_object_permissions(request, obj)
в представлении в тот момент, когда вы извлекли объект.
Это либо вызовет исключение PermissionDenied
или NotAuthenticated
, либо просто вернет, если представление имеет соответствующие разрешения.
Например:
Примечание: За исключением DjangoObjectPermissions
, предоставленные классы разрешений в rest_framework.permissions
не реализуют методы, необходимые для проверки разрешений объектов.
Если вы хотите использовать предоставленные классы разрешений для проверки разрешений объектов, вы должны подклассифицировать их и реализовать метод has_object_permission()
, описанный в разделе Пользовательские разрешения (ниже).
Ограничения разрешений на уровне объекта
По причинам производительности общие представления не будут автоматически применять разрешения на уровне объекта к каждому экземпляру в наборе запросов при возврате списка объектов.
Часто при использовании разрешений на уровне объектов вы также хотите фильтровать QuerySet соответствующим образом, чтобы убедиться, что пользователи имеют возможность просматривать только те экземпляры, которые им разрешено просматривать.
Поскольку метод get_object()
не вызывается, разрешения объектного уровня из метода has_object_permission()
не применяются при создании объектов. Чтобы ограничить создание объектов, вам необходимо реализовать проверку разрешений либо в классе Serializer, либо переопределить метод perform_create()
вашего класса ViewSet.
Установка политики разрешений
Политика разрешений по умолчанию может быть установлена глобально с помощью параметра DEFAULT_PERMISSION_CLASSES
. Например.
Если этот параметр не указан, то по умолчанию он разрешает неограниченный доступ:
Вы также можете установить политику аутентификации на основе каждого представления или каждого набора представлений, используя представления на основе класса APIView
.
Или, если вы используете декоратор @api_view
с представлениями, основанными на функциях.
Примечание: когда вы устанавливаете новые классы разрешений с помощью атрибута class или декораторов, вы говорите представлению игнорировать список по умолчанию, установленный в файле settings.py.
При условии наследования от rest_framework.permissions.BasePermission
, разрешения могут быть составлены с использованием стандартных побитовых операторов Python. Например, IsAuthenticatedOrReadOnly
может быть записано:
Примечание: он поддерживает & (и), | (или) и ~ (не).
API Reference
AllowAny
Класс разрешения AllowAny
разрешает неограниченный доступ, независимо от того, был ли запрос аутентифицирован или неаутентифицирован.
Это разрешение не является строго обязательным, поскольку вы можете достичь того же результата, используя пустой список или кортеж для установки разрешений, но вы можете посчитать полезным указать этот класс, поскольку он делает намерение явным.
IsAuthenticated
Класс разрешения IsAuthenticated
будет запрещать разрешение любому пользователю, не прошедшему аутентификацию, и разрешать в противном случае.
Это разрешение подходит, если вы хотите, чтобы ваш API был доступен только зарегистрированным пользователям.
IsAdminUser
Класс разрешения IsAdminUser
запрещает разрешение любому пользователю, если только user.is_staff
не является True
, в этом случае разрешение будет разрешено.
Это разрешение подходит, если вы хотите, чтобы ваш API был доступен только подгруппе доверенных администраторов.
IsAuthenticatedOrReadOnly
Параметр IsAuthenticatedOrReadOnly
позволит аутентифицированным пользователям выполнять любые запросы. Запросы для неаутентифицированных пользователей будут разрешены, только если метод запроса является одним из "безопасных" методов: GET
, HEAD
или OPTIONS
.
Это разрешение подходит, если вы хотите, чтобы ваш API разрешал разрешения на чтение анонимным пользователям и разрешал разрешения на запись только аутентифицированным пользователям.
DjangoModelPermissions
Этот класс разрешений связан со стандартными разрешениями Django django.contrib.auth
model permissions. Это разрешение должно применяться только к представлениям, имеющим свойство .queryset
или метод get_queryset()
. Авторизация будет предоставлена только в том случае, если пользователь аутентифицирован и имеет соответствующие разрешения модели. Соответствующая модель определяется путем проверки get_queryset().model
или queryset.model
.
POST
-запросы требуют от пользователя разрешенияadd
на модель.PUT
-запросы иPATCH
-запросы требуют от пользователя разрешенияchange
модель.DELETE
-запросы требуют от пользователя разрешенияdelete
на модель.
Поведение по умолчанию также может быть переопределено для поддержки пользовательских разрешений модели. Например, вы можете включить разрешение модели view
для запросов GET
.
Чтобы использовать пользовательские разрешения модели, переопределите DjangoModelPermissions
и установите свойство .perms_map
. Подробности см. в исходном коде.
DjangoModelPermissionsOrAnonReadOnly
Аналогичен DjangoModelPermissions
, но также позволяет неаутентифицированным пользователям иметь доступ к API только для чтения.
DjangoObjectPermissions
Этот класс разрешений связан со стандартным object permissions framework Django, который позволяет устанавливать разрешения на модели на уровне объектов. Чтобы использовать этот класс разрешений, вам также необходимо добавить бэкенд разрешений, который поддерживает разрешения на уровне объектов, например django-guardian.
Как и DjangoModelPermissions
, это разрешение должно применяться только к представлениям, имеющим свойство .queryset
или метод .get_queryset()
. Разрешение будет предоставлено только в том случае, если пользователь аутентифицирован и имеет соответствующие разрешения на объект и соответствующие разрешения на модель.
POST
-запросы требуют, чтобы пользователь имел разрешениеadd
на экземпляр модели.PUT
-запросы иPATCH
-запросы требуют от пользователя разрешенияизменить
на экземпляре модели.DELETE
-запросы требуют от пользователя разрешенияdelete
на экземпляр модели.
Обратите внимание, что DjangoObjectPermissions
не требует пакета django-guardian
, и должен одинаково хорошо поддерживать другие бэкенды объектного уровня.
Как и в случае с DjangoModelPermissions
, вы можете использовать пользовательские разрешения модели, переопределив DjangoObjectPermissions
и установив свойство .perms_map
. Подробности смотрите в исходном коде.
Примечание: Если вам нужны разрешения view
на уровне объектов для запросов GET
, HEAD
и OPTIONS
и вы используете django-guardian для бэкенда разрешений на уровне объектов, вам стоит рассмотреть возможность использования класса DjangoObjectPermissionsFilter
, предоставляемого пакетом djangorestframework-guardian2
. Он гарантирует, что конечные точки списка возвращают только те результаты, включающие объекты, для которых у пользователя есть соответствующие разрешения на просмотр.
Пользовательские разрешения
Чтобы реализовать пользовательское разрешение, переопределите BasePermission
и реализуйте один или оба из следующих методов:
.has_permission(self, request, view)
.has_object_permission(self, request, view, obj)
Методы должны возвращать True
, если запрос должен получить доступ, и False
в противном случае.
Если вам нужно проверить, является ли запрос операцией чтения или записи, вы должны проверить метод запроса по константе SAFE_METHODS
, которая представляет собой кортеж, содержащий 'GET'
, 'OPTIONS'
и 'HEAD'
. Например:
Примечание: Метод has_object_permission
на уровне экземпляра будет вызван только в том случае, если проверки has_permission
на уровне представления уже прошли. Также обратите внимание, что для того, чтобы проверки на уровне экземпляра были выполнены, код представления должен явно вызвать .check_object_permissions(request, obj)
. Если вы используете общие представления, то это будет сделано за вас по умолчанию. (Представления, основанные на функциях, должны будут проверять разрешения объектов явно, выдавая при неудаче сообщение PermissionDenied
).
Пользовательские разрешения вызовут исключение PermissionDenied
, если тест не пройдет. Чтобы изменить сообщение об ошибке, связанное с исключением, реализуйте атрибут message
непосредственно для вашего пользовательского разрешения. В противном случае будет использоваться атрибут default_detail
из PermissionDenied
. Аналогично, чтобы изменить идентификатор кода, связанный с исключением, реализуйте атрибут code
непосредственно для вашего пользовательского разрешения - иначе будет использоваться атрибут default_code
из PermissionDenied
.
Примеры
Ниже приведен пример класса разрешения, который проверяет IP-адрес входящего запроса по списку блокировки и отклоняет запрос, если IP-адрес был заблокирован.
Помимо глобальных разрешений, которые выполняются для всех входящих запросов, вы также можете создавать разрешения на уровне объекта, которые выполняются только для операций, затрагивающих конкретный экземпляр объекта. Например:
Обратите внимание, что общие представления будут проверять соответствующие разрешения на уровне объекта, но если вы пишете свои собственные пользовательские представления, вам нужно убедиться, что вы сами проверяете разрешения на уровне объекта. Вы можете сделать это, вызвав self.check_object_permissions(request, obj)
из представления, когда у вас есть экземпляр объекта. Этот вызов вызовет соответствующее исключение APIException
, если проверка разрешений на уровне объекта завершится неудачей, а в противном случае просто вернется.
Также обратите внимание, что общие представления будут проверять разрешения на уровне объекта только для представлений, которые получают один экземпляр модели. Если вам требуется фильтрация представлений списка на уровне объектов, вам нужно будет фильтровать набор запросов отдельно. Более подробную информацию смотрите в документации filtering documentation.
Обзор методов ограничения доступа
DRF предлагает три различных метода настройки ограничений доступа в каждом конкретном случае. Они применяются в разных сценариях и имеют различные эффекты и ограничения.
queryset
/get_queryset()
: Ограничивает общую видимость существующих объектов из базы данных. Кверисет ограничивает, какие объекты будут отображаться в списке и какие объекты могут быть изменены или удалены. Методget_queryset()
может применять различные кверисеты в зависимости от текущего действия.permission_classes
/get_permissions()
: Общая проверка разрешений на основе текущего действия, запроса и целевого объекта. Разрешения на уровне объекта могут быть применены только к действиям получения, изменения и удаления. Проверки разрешений дляlist
иcreate
будут применены ко всему типу объекта. (В случае списка: с учетом ограничений в наборе запросов).serializer_class
/get_serializer()
: Ограничения на уровне экземпляра, которые применяются ко всем объектам на входе и выходе. Сериализатор может иметь доступ к контексту запроса. Методget_serializer()
может применять различные сериализаторы в зависимости от текущего действия.
В следующей таблице перечислены методы ограничения доступа и уровень контроля, который они обеспечивают, над какими действиями.
* Класс Serializer не должен поднимать PermissionDenied в действии со списком, иначе весь список не будет возвращен.
** Методы get_*()
имеют доступ к текущему представлению и могут возвращать различные экземпляры Serializer или QuerySet в зависимости от запроса или действия.
Пакеты сторонних производителей
Также доступны следующие пакеты сторонних производителей.
Django REST - Access Policy
Пакет Django REST - Access Policy предоставляет способ определения сложных правил доступа в декларативных классах политик, которые прикрепляются к наборам представлений или представлениям на основе функций. Политики определяются в JSON в формате, аналогичном политикам AWS Identity & Access Management.
Composed Permissions
Пакет Composed Permissions предоставляет простой способ определения сложных и многомерных (с логическими операторами) объектов разрешений, используя небольшие и многократно используемые компоненты.
REST Condition
Пакет REST Condition - это еще одно расширение для построения сложных разрешений простым и удобным способом. Расширение позволяет комбинировать разрешения с логическими операторами.
DRY Rest Permissions
Пакет DRY Rest Permissions предоставляет возможность определять различные разрешения для отдельных действий по умолчанию и пользовательских действий. Этот пакет предназначен для приложений с разрешениями, которые являются производными от отношений, определенных в модели данных приложения. Он также поддерживает проверку разрешений, возвращаемую клиентскому приложению через сериализатор API. Кроме того, он поддерживает добавление разрешений к действиям списка по умолчанию и пользовательским действиям списка для ограничения данных, которые они извлекают для каждого пользователя.
Django Rest Framework Roles
Пакет Django Rest Framework Roles облегчает параметризацию вашего API для нескольких типов пользователей.
Rest Framework Roles
Rest Framework Roles позволяет очень просто защитить представления на основе ролей. Самое главное - позволяет вам отделить логику доступности от моделей и представлений чистым человекочитаемым способом.
Django REST Framework API Key
Пакет Django REST Framework API Key предоставляет классы разрешений, модели и помощники для добавления авторизации по API ключу в ваш API. Его можно использовать для авторизации внутренних или сторонних бэкендов и сервисов (т.е. машин), которые не имеют учетной записи пользователя. API ключи хранятся в безопасном месте с использованием инфраструктуры хэширования паролей Django, и их можно просматривать, редактировать и отзывать в любое время в админке Django.
Django Rest Framework Role Filters
Пакет Django Rest Framework Role Filters обеспечивает простую фильтрацию по нескольким типам ролей.
Django Rest Framework PSQ
Пакет Django Rest Framework PSQ - это расширение, которое предоставляет поддержку для использования основанных на действиях permission_classes, serializer_class и queryset, зависящих от правил, основанных на разрешениях.
Last updated