La autenticación o identificación por sí sola no suele ser suficiente para acceder a la información o al código. Para eso, la entidad que solicita el acceso debe tener autorización.

Documentación para desarrolladores de Apple

Junto con la autenticación y la limitación, los permisos determinan si se debe otorgar o denegar el acceso a una solicitud.

Las comprobaciones de permisos siempre se ejecutan al comienzo de la vista, antes de que se permita continuar con cualquier otro código. Las comprobaciones de permisos normalmente utilizarán la información de autenticación en el request.user y request.auth properties para determinar si se debe permitir la solicitud entrante.

Los permisos se utilizan para otorgar o denegar el acceso de diferentes clases de usuarios a diferentes partes de la API.

El estilo de permiso más simple sería permitir el acceso a cualquier usuario autenticado y denegar el acceso a cualquier usuario no autenticado. Esto corresponde a la IsAuthenticated clase en el marco REST.

Un estilo de permiso un poco menos estricto sería permitir el acceso completo a los usuarios autenticados, pero permitir el acceso de solo lectura a los usuarios no autenticados. Esto corresponde a la IsAuthenticatedOrReadOnly clase en el marco REST.

Cómo se determinan los permisos

Los permisos en el marco REST siempre se definen como una lista de clases de permisos.

Antes de ejecutar el cuerpo principal de la vista, se comprueban todos los permisos de la lista. Si alguna verificación de permisos falla un exceptions.PermissionDenied o exceptions.NotAuthenticated Se generará una excepción y el cuerpo principal de la vista no se ejecutará.

Cuando las comprobaciones de permisos fallan, se devolverá una respuesta “403 Prohibido” o “401 No autorizado”, de acuerdo con las siguientes reglas:

  • La solicitud se autenticó correctamente, pero se denegó el permiso. – Se devolverá una respuesta HTTP 403 Prohibido.
  • La solicitud no se autenticó correctamente y la clase de autenticación de mayor prioridad no usar WWW-Authenticate encabezados. – Se devolverá una respuesta HTTP 403 Prohibido.
  • La solicitud no se autenticó correctamente y la clase de autenticación de mayor prioridad lo hace usar WWW-Authenticate encabezados. – Una respuesta HTTP 401 no autorizada, con un WWW-Authenticate se devolverá el encabezado.

Permisos a nivel de objeto

Los permisos del marco REST también admiten permisos a nivel de objeto. Los permisos a nivel de objeto se utilizan para determinar si un usuario debe poder actuar sobre un objeto en particular, que normalmente será una instancia de modelo.

Los permisos de nivel de objeto son ejecutados por las vistas genéricas del marco REST cuando .get_object() se llama. Al igual que con los permisos de nivel de vista, exceptions.PermissionDenied Se generará una excepción si el usuario no puede actuar sobre el objeto dado.

Si está escribiendo sus propias vistas y desea hacer cumplir los permisos a nivel de objeto, o si anula la get_object en una vista genérica, entonces deberá llamar explícitamente al .check_object_permissions(request, obj) en la vista en el punto en el que recuperó el objeto.

Esto generará un PermissionDenied o NotAuthenticated excepción, o simplemente regresar si la vista tiene los permisos apropiados.

Por ejemplo:

defget_object(self):
    obj = get_object_or_404(self.get_queryset(), pk=self.kwargs["pk"])
    self.check_object_permissions(self.request, obj)return obj

Nota: Con la excepción de DjangoObjectPermissions, las clases de permisos proporcionadas en rest_framework.permissionsno implementar los métodos necesarios para verificar los permisos de los objetos.

Si desea utilizar las clases de permisos proporcionadas para verificar los permisos de los objetos, usted debe subclasificarlos e implementar el has_object_permission() método descrito en el Permisos personalizados sección (a continuación).

Limitaciones de los permisos a nivel de objeto

Por motivos de rendimiento, las vistas genéricas no aplicarán automáticamente permisos de nivel de objeto a cada instancia en un conjunto de consultas al devolver una lista de objetos.

A menudo, cuando usa permisos de nivel de objeto, también querrá filtrar el conjunto de consultas de manera adecuada, para asegurarse de que los usuarios solo tengan visibilidad de las instancias que pueden ver.

Establecer la política de permisos

La política de permisos predeterminada se puede establecer globalmente, utilizando el DEFAULT_PERMISSION_CLASSES configuración. Por ejemplo.

REST_FRAMEWORK ='DEFAULT_PERMISSION_CLASSES':['rest_framework.permissions.IsAuthenticated',]

Si no se especifica, esta configuración predeterminada permite el acceso sin restricciones:

'DEFAULT_PERMISSION_CLASSES':['rest_framework.permissions.AllowAny',]

También puede configurar la política de autenticación por vista o por conjunto de vista, utilizando el APIView vistas basadas en clases.

from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

classExampleView(APIView):
    permission_classes =[IsAuthenticated]defget(self, request,format=None):
        content ='status':'request was permitted'return Response(content)

O, si está utilizando el @api_view decorador con vistas basadas en funciones.

from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

@api_view(['GET'])@permission_classes([IsAuthenticated])defexample_view(request,format=None):
    content ='status':'request was permitted'return Response(content)

Nota: cuando establece nuevas clases de permisos a través del atributo de clase o decoradores, le está diciendo a la vista que ignore la lista predeterminada establecida sobre el settings.py expediente.

Siempre que hereden de rest_framework.permissions.BasePermission, los permisos se pueden componer utilizando operadores bit a bit estándar de Python. Por ejemplo, IsAuthenticatedOrReadOnly podría escribirse:

from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS
from rest_framework.response import Response
from rest_framework.views import APIView

classReadOnly(BasePermission):defhas_permission(self, request, view):return request.method in SAFE_METHODS

classExampleView(APIView):
    permission_classes =[IsAuthenticated|ReadOnly]defget(self, request,format=None):
        content ='status':'request was permitted'return Response(content)

Nota: admite & (y), | (o) y ~ (no).

AllowAny

los AllowAny la clase de permiso permitirá el acceso sin restricciones, independientemente de si la solicitud fue autenticada o no autenticada.

Este permiso no es estrictamente necesario, ya que puede lograr el mismo resultado utilizando una lista vacía o tupla para la configuración de permisos, pero puede resultarle útil especificar esta clase porque hace explícita la intención.

Está autenticado

los IsAuthenticated La clase de permiso denegará el permiso a cualquier usuario no autenticado y permitirá el permiso en caso contrario.

Este permiso es adecuado si desea que su API solo sea accesible para usuarios registrados.

IsAdminUser

los IsAdminUser La clase de permiso denegará el permiso a cualquier usuario, a menos que user.is_staff es True en cuyo caso se permitirá el permiso.

Este permiso es adecuado si desea que su API solo sea accesible para un subconjunto de administradores de confianza.

IsAuthenticatedOrReadOnly

los IsAuthenticatedOrReadOnly permitirá a los usuarios autenticados realizar cualquier solicitud. Las solicitudes de usuarios no autorizados solo se permitirán si el método de solicitud es uno de los métodos “seguros”; GET, HEAD o OPTIONS.

Este permiso es adecuado si desea que su API permita permisos de lectura a usuarios anónimos y solo permita permisos de escritura a usuarios autenticados.

DjangoModelPermissions

Esta clase de permiso se relaciona con el estándar de Django django.contrib.authpermisos de modelo. Este permiso solo se debe aplicar a las vistas que tienen un .queryset conjunto de propiedades. La autorización solo se otorgará si el usuario está autenticado y tiene el permisos de modelo relevantes asignado.

  • POST las solicitudes requieren que el usuario tenga la add permiso sobre el modelo.
  • PUT y PATCH las solicitudes requieren que el usuario tenga la change permiso sobre el modelo.
  • DELETE las solicitudes requieren que el usuario tenga la delete permiso sobre el modelo.

El comportamiento predeterminado también se puede anular para admitir permisos de modelos personalizados. Por ejemplo, es posible que desee incluir un view permiso modelo para GET peticiones.

Para usar permisos de modelos personalizados, anule DjangoModelPermissions y establecer el .perms_map propiedad. Consulte el código fuente para obtener más detalles.

Se usa con vistas que no incluyen un atributo de conjunto de consultas.

Si está usando este permiso con una vista que usa una anulación get_queryset() método puede que no haya un queryset atributo en la vista. En este caso, sugerimos también marcar la vista con un conjunto de consultas centinela, para que esta clase pueda determinar los permisos necesarios. Por ejemplo:

queryset = User.objects.none()# Required for DjangoModelPermissions

DjangoModelPermissionsOrAnonReadOnly

Similar a DjangoModelPermissions, pero también permite que los usuarios no autenticados tengan acceso de solo lectura a la API.

DjangoObjectPermissions

Esta clase de permiso se relaciona con el estándar de Django marco de permisos de objeto que permite permisos por objeto en modelos. Para utilizar esta clase de permiso, también deberá agregar un backend de permisos que admita permisos a nivel de objeto, como django-guardian.

Al igual que con DjangoModelPermissions, este permiso solo debe aplicarse a las vistas que tienen un .queryset propiedad o .get_queryset() método. La autorización solo se otorgará si el usuario está autenticado y tiene el permisos relevantes por objeto y permisos de modelo relevantes asignado.

  • POST las solicitudes requieren que el usuario tenga la add permiso en la instancia del modelo.
  • PUT y PATCH las solicitudes requieren que el usuario tenga la change permiso en la instancia del modelo.
  • DELETE las solicitudes requieren que el usuario tenga la delete permiso en la instancia del modelo.

Tenga en cuenta que DjangoObjectPermissionsno requieren el django-guardian package, y debería admitir otros backends a nivel de objeto igualmente bien.

Al igual que con DjangoModelPermissions puede utilizar permisos de modelos personalizados anulando DjangoObjectPermissions y estableciendo el .perms_map propiedad. Consulte el código fuente para obtener más detalles.

Nota: Si necesita nivel de objeto view permisos para GET, HEAD y OPTIONS solicitudes y están usando django-guardian para su backend de permisos a nivel de objeto, querrá considerar usar el DjangoObjectPermissionsFilter clase proporcionada por el djangorestframework-guardian paquete. Garantiza que los puntos finales de la lista solo devuelvan resultados, incluidos los objetos para los que el usuario tiene los permisos de visualización adecuados.

Para implementar un permiso personalizado, anule BasePermission e implementar uno o ambos de los siguientes métodos:

  • .has_permission(self, request, view)
  • .has_object_permission(self, request, view, obj)

Los métodos deberían volver True si se debe conceder acceso a la solicitud, y False de lo contrario.

Si necesita probar si una solicitud es una operación de lectura o una operación de escritura, debe verificar el método de solicitud con la constante SAFE_METHODS, que es una tupla que contiene 'GET', 'OPTIONS' y 'HEAD'. Por ejemplo:

if request.method in permissions.SAFE_METHODS:# Check permissions for read-only requestelse:# Check permissions for write request

Nota: El nivel de instancia has_object_permission solo se llamará al método si el nivel de vista has_permission los controles ya han pasado. También tenga en cuenta que para que se ejecuten las comprobaciones a nivel de instancia, el código de vista debe llamar explícitamente .check_object_permissions(request, obj). Si esta usando las vistas genéricas, entonces esto se manejará por usted de forma predeterminada. (Las vistas basadas en funciones necesitarán verificar los permisos de los objetos explícitamente, aumentando PermissionDenied en caso de falla.)

Los permisos personalizados generarán un PermissionDenied excepción si la prueba falla. Para cambiar el mensaje de error asociado con la excepción, implemente un message atributo directamente en su permiso personalizado. De lo contrario, el default_detail atributo de PermissionDenied se utilizará.

from rest_framework import permissions

classCustomerAccessPermission(permissions.BasePermission):
    message ='Adding customers not allowed.'defhas_permission(self, request, view):...

Ejemplos de

El siguiente es un ejemplo de una clase de permiso que verifica la dirección IP de la solicitud entrante con una lista negra y niega la solicitud si la IP ha sido incluida en la lista negra.

from rest_framework import permissions

classBlacklistPermission(permissions.BasePermission):"""
    Global permission check for blacklisted IPs.
    """defhas_permission(self, request, view):
        ip_addr = request.META['REMOTE_ADDR']
        blacklisted = Blacklist.objects.filter(ip_addr=ip_addr).exists()returnnot blacklisted

Además de los permisos globales, que se ejecutan en todas las solicitudes entrantes, también puede crear permisos a nivel de objeto, que solo se ejecutan en operaciones que afectan a una instancia de objeto en particular. Por ejemplo:

classIsOwnerOrReadOnly(permissions.BasePermission):"""
    Object-level permission to only allow owners of an object to edit it.
    Assumes the model instance has an `owner` attribute.
    """defhas_object_permission(self, request, view, obj):# Read permissions are allowed to any request,# so we'll always allow GET, HEAD or OPTIONS requests.if request.method in permissions.SAFE_METHODS:returnTrue# Instance must have an attribute named `owner`.return obj.owner == request.user

Tenga en cuenta que las vistas genéricas verificarán los permisos de nivel de objeto apropiados, pero si está escribiendo sus propias vistas personalizadas, deberá asegurarse de verificar las verificaciones de permisos de nivel de objeto usted mismo. Puedes hacerlo llamando self.check_object_permissions(request, obj) desde la vista una vez que tenga la instancia del objeto. Esta llamada generará un APIException si fallan las comprobaciones de permisos a nivel de objeto y, de lo contrario, simplemente volverán.

También tenga en cuenta que las vistas genéricas solo comprobarán los permisos a nivel de objeto para las vistas que recuperan una única instancia de modelo. Si necesita un filtrado a nivel de objeto de las vistas de lista, deberá filtrar el conjunto de consultas por separado. Consulte la documentación de filtrado para obtener más detalles.

Los siguientes paquetes de terceros también están disponibles.

DRF – Política de acceso

los Django REST – Política de acceso El paquete proporciona una forma de definir reglas de acceso complejas en clases de políticas declarativas que se adjuntan a conjuntos de vistas o vistas basadas en funciones. Las políticas se definen en JSON en un formato similar a las políticas de administración de acceso e identidad de AWS.

Permisos compuestos

los Permisos compuestos El paquete proporciona una forma sencilla de definir objetos de permisos complejos y de múltiples profundidades (con operadores lógicos), utilizando componentes pequeños y reutilizables.

Condición de reposo

los Condición de reposo package es otra extensión para crear permisos complejos de una manera simple y conveniente. La extensión le permite combinar permisos con operadores lógicos.

Permisos de descanso SECO

los Permisos de descanso SECO El paquete proporciona la capacidad de definir diferentes permisos para acciones individuales predeterminadas y personalizadas. Este paquete está hecho para aplicaciones con permisos que se derivan de relaciones definidas en el modelo de datos de la aplicación. También es compatible con las comprobaciones de permisos que se devuelven a una aplicación cliente a través del serializador de la API. Además, admite la adición de permisos a las acciones de la lista predeterminada y personalizada para restringir los datos que recuperan por usuario.

Roles de Django Rest Framework

los Roles de Django Rest Framework El paquete facilita la parametrización de su API en varios tipos de usuarios.

Clave de API de Django REST Framework

los Clave de API de Django REST Framework El paquete proporciona clases de permisos, modelos y ayudantes para agregar autorización de clave API a su API. Se puede utilizar para autorizar backends y servicios internos o de terceros (p. Ej. máquinas) que no tienen una cuenta de usuario. Las claves de API se almacenan de forma segura utilizando la infraestructura de hash de contraseñas de Django, y se pueden ver, editar y revocar en cualquier momento en el administrador de Django.

Filtros de roles de Django Rest Framework

los Filtros de roles de Django Rest Framework El paquete proporciona un filtrado simple sobre múltiples tipos de roles.

permissions.py