Hay muchos escenarios diferentes a considerar cuando se trata de control de acceso. Permitir el acceso no autorizado a operaciones de riesgo o áreas restringidas da como resultado una vulnerabilidad masiva. Esto resalta la importancia de agregar permisos en las API.
El marco Django REST nos permite aprovechar los permisos para definir a qué se puede acceder y qué acciones se pueden realizar de manera significativa o común. Las comprobaciones de permisos siempre se ejecutan al principio de cada vista. Utiliza la información de autenticación en las propiedades ‘request.user’ y ‘request.auth’ para cada solicitud entrante. Si la verificación de permisos falla, el código de vista no se ejecutará.
Nota: junto con la autenticación, los permisos determinan si conceder o denegar el acceso a una solicitud entrante. En esta sección, combinaremos la autenticación básica con el permiso del marco REST de Django para establecer el control de acceso. Puede consultar la API navegable en Django REST Framework para modelos, serializadores y vistas
Profundicemos en los permisos del marco REST de Django.
- PermitirCualquiera
- Está autenticado
- EsUsuarioAdmin
- Está autenticado o solo leído
- DjangoModelPermissions
- DjangoModelPermissionsOrAnonReadOnly
- DjangoObjectPermissions
PermitirCualquiera
La clase de permiso AllowAny permitirá el acceso sin restricciones, independientemente de si la solicitud fue autenticada o no. Aquí la configuración de permisos predeterminada para acceso sin restricciones
'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.AllowAny', ]
No es necesario establecer este permiso, pero se recomienda mencionarlo para que la intención sea explícita. Además de mencionarlo globalmente, puede establecer la política de permisos por vista. Si está utilizando las vistas basadas en la clase APIView, el código es el siguiente
Python3
from rest_framework.permissions import AllowAny from rest_framework.response import Response from rest_framework.views import APIView class ClassBasedView(APIView): permission_classes = [AllowAny] def get(self, request, format=None): content = { 'status': 'request was permitted' } return Response(content)
Al usar el decorador @api_view con vistas basadas en funciones, el código es el siguiente
Python3
from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import AllowAny from rest_framework.response import Response @api_view(['GET']) @permission_classes([AllowAny]) def function_view(request, format=None): content = { 'status': 'request was permitted' } return Response(content)
Está autenticado
La clase de permiso IsAuthenticated niega a los usuarios no autenticados el uso de las API para cualquier operación. Esto garantiza la accesibilidad de las API solo para usuarios registrados. Usemos la clase IsAuthenticated en nuestro servicio web RESTful. Aquí, podemos establecer la política de permisos por visualización. Importemos y agreguemos la clase de permiso en nuestra clase RobotDetail y RobotList. El código es el siguiente:
from rest_framework.permissions import IsAuthenticated
Python3
class RobotDetail(generics.RetrieveUpdateDestroyAPIView): permission_classes = [IsAuthenticated] queryset = Robot.objects.all() serializer_class = RobotSerializer name = 'robot-detail' class RobotList(generics.ListCreateAPIView): permission_classes = [IsAuthenticated] queryset = Robot.objects.all() serializer_class = RobotSerializer name = 'robot-list'
Intentemos recuperar robots sin proporcionar ninguna credencial. El comando HTTPie es
http:8000/robot/
Producción
Dado que no proporcionamos ningún detalle de autenticación, la API rechazó la solicitud que recupera los detalles del robot. Ahora crearemos un nuevo usuario usando el shell interactivo de Django y probaremos el comando HTTPie con credenciales.
Nota: puede consultar el artículo Crear un usuario para Django usando el shell interactivo de Django .
El comando HTTPie es el siguiente:
http -a “sonu”:”sn@pswrd” :8000/robot/
Producción
Probemos un comando HTTPie que crea una nueva entrada de robot.
http -a “sonu”:”sn@pswrd” POST :8000/robot/ name=”IRB 1100″ robot_category=”Articulated Robots” currency=”USD” price=25000 manufacturer=”ABB” manufacturing_date=”2020-05- 10 00:00:00+00:00″
Producción
EsUsuarioAdmin
La clase de permiso IsAdminUser otorgará permiso a los usuarios cuyo user.is_staff sea True. Esta clase de permiso garantiza que los administradores de confianza puedan acceder a la API. Hagamos uso de la clase de permiso IsAdminUser. Importemos la clase de permiso.
from rest_framework.permissions import IsAdminUser
Puede reemplazar la clase RobotDetail y RobotList con el siguiente código.
Python3
class RobotDetail(generics.RetrieveUpdateDestroyAPIView): permission_classes = [IsAdminUser] queryset = Robot.objects.all() serializer_class = RobotSerializer name = 'robot-detail' class RobotList(generics.ListCreateAPIView): permission_classes = [IsAdminUser] queryset = Robot.objects.all() serializer_class = RobotSerializer name = 'robot-list'
Ahora intentemos proporcionar credenciales de usuario normales. El comando HTTPie es
http -a “sonu”:”sn@pswrd” :8000/robot/
Producción
Puede notar el mensaje que dice «No tiene permiso para realizar esta acción». Esto se debe a que el usuario no es un administrador. Proporcionemos nuestras credenciales de superadministrador. El comando HTTPie es
http -a “admin”:”admin@123″ :8000/robot/
Producción
Está autenticado o solo leído
La clase de permiso IsAuthenticatedOrReadOnly permite a los usuarios no autorizados realizar métodos seguros, mientras que los usuarios autenticados pueden realizar cualquier operación. Esta clase es útil cuando necesitamos establecer permisos de lectura para usuarios anónimos y permisos de lectura/escritura para usuarios autenticados. Importemos la clase de permiso.
from rest_framework.permissions import IsAuthenticatedOrReadOnly
Ahora, puede reemplazar la clase RobotDetail y RobotList con el siguiente código.
Python3
class RobotList(generics.ListCreateAPIView): permission_classes = [IsAuthenticatedOrReadOnly] queryset = Robot.objects.all() serializer_class = RobotSerializer name = 'robot-list' class RobotDetail(generics.RetrieveUpdateDestroyAPIView): permission_classes = [IsAuthenticatedOrReadOnly] queryset = Robot.objects.all() serializer_class = RobotSerializer name = 'robot-detail'
Intentemos recuperar los detalles del robot sin proporcionar ninguna credencial. El comando HTTPie es el siguiente:
http:8000/robot/
Producción
Ahora intentemos crear un nuevo robot sin proporcionar credenciales. El comando HTTPie es el siguiente:
http POST :8000/robot/ name=”IRB 120″ robot_category=”Articulated Robots” currency=”USD” price=35000 manufacturer=”ABB” manufacturing_date=”2020-08-10 00:00:00+00:00″
Producción
La clase de permiso IsAuthenticatedOrReadOnly solo permite operaciones seguras para usuarios no autenticados. Vamos a crear un nuevo robot proporcionando credenciales de usuario.
http -a “sonu”:”sn@pswrd” POST :8000/robot/ name=”IRB 120″ robot_category=”Articulated Robots” currency=”USD” price=35000 manufacturer=”ABB” manufacturing_date=”2020-08- 10 00:00:00+00:00″
Producción
DjangoModelPermissions
En la clase DjangoModelPermissions, la autenticación se otorga solo si el usuario está autenticado y tiene asignados los permisos de modelo relevantes. Los permisos del modelo son los siguientes
- El usuario debe tener el permiso add en el modelo para realizar requests POST.
- El usuario debe tener el permiso de cambio en el modelo para realizar requests PUT y PATCH.
- El usuario debe tener el permiso de eliminación en el modelo para realizar requests de ELIMINACIÓN.
De forma predeterminada, la clase permite requests GET para usuarios autenticados. La clase DjangoModelPermissions se relaciona con los permisos del modelo django.contrib.auth estándar de Django . Solo debe aplicarse a vistas que tengan una propiedad .queryset o un método get_queryset().
Puede importar la clase DjangoModelPermissions.
from rest_framework.permissions import DjangoModelPermissions
A continuación, reemplace la clase RobotDetail y RobotList con el siguiente código.
Python3
class RobotList(generics.ListCreateAPIView): permission_classes = [DjangoModelPermissions] queryset = Robot.objects.all() serializer_class = RobotSerializer name = 'robot-list' class RobotDetail(generics.RetrieveUpdateDestroyAPIView): permission_classes = [DjangoModelPermissions] queryset = Robot.objects.all() serializer_class = RobotSerializer name = 'robot-detail'
Intentemos crear un robot proporcionando credenciales de usuario. El comando HTTPie de la siguiente manera:
http -a “sonu”:”sn@pswrd” POST :8000/robot/ name=”IRB 140″ robot_category=”Articulated Robots” currency=”USD” price=35000 manufacturer=”ABB” manufacturing_date=”2021-01- 10 00:00:00+00:00″
Producción
Puede notar que se deniega el permiso para crear un robot. Esto se debe a que no hemos establecido permisos a nivel de modelo para el usuario dado. Para establecer el permiso para agregar un robot, puede iniciar sesión a través del panel de administración como superusuario y agregar el permiso seleccionando el usuario en la sección Usuarios. Finalmente, guarde los cambios. Compartiendo la captura de pantalla a continuación:
Intentemos nuevamente el mismo comando HTTPie.
http -a “sonu”:”sn@pswrd” POST :8000/robot/ name=”IRB 140″ robot_category=”Articulated Robots” currency=”USD” price=35000 manufacturer=”ABB” manufacturing_date=”2021-01- 10 00:00:00+00:00″
Producción
DjangoModelPermissionsOrAnonReadOnly
La clase de permiso DjangoModelPermissionsOrAnonReadOnly es la misma que la clase DjangoModelPermissions, excepto que permite a los usuarios no autenticados tener acceso de solo lectura a la API.
Importemos la clase DjangoModelPermissionsOrAnonReadOnly.
from rest_framework.permissions import DjangoModelPermissionsOrAnonReadOnly
Ahora puede agregar la clase de permiso a la clase RobotDetail y RobotList. El código es el siguiente:
Python3
class RobotList(generics.ListCreateAPIView): permission_classes = [DjangoModelPermissionsOrAnonReadOnly] queryset = Robot.objects.all() serializer_class = RobotSerializer name = 'robot-list' class RobotDetail(generics.RetrieveUpdateDestroyAPIView): permission_classes = [DjangoModelPermissionsOrAnonReadOnly] queryset = Robot.objects.all() serializer_class = RobotSerializer name = 'robot-detail'
Intentemos recuperar robots sin proporcionar ninguna credencial. El comando HTTPie es el siguiente:
http:8000/robot/
Producción
DjangoObjectPermissions
DjangoObjectPermissions permite permisos por objeto en modelos, que pueden establecer permisos para filas individuales en una tabla (instancias de modelo). El usuario debe estar autenticado para otorgar la autorización y se le deben asignar los permisos relevantes por objeto y los permisos de modelo relevantes. Para establecer permisos relevantes por objeto, necesitamos crear una subclase de DjangoObjectPermissions e implementar el método has_object_permission(). Los permisos de modelo relevantes son los siguientes:
- El usuario debe tener el permiso de agregar en el modelo para realizar requests POST.
- El usuario debe tener el permiso de cambio en el modelo para realizar requests PUT y PATCH.
- El usuario debe tener el permiso de eliminación en el modelo para realizar requests de ELIMINACIÓN.
Con DjangoModelPermissions puede crear permisos de modelos personalizados anulando DjangoObjectPermissions. Puede verificar la personalización del permiso de nivel de objeto en Django REST Framework .
Publicación traducida automáticamente
Artículo escrito por SonuGeorge y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA