Resumo : neste tutorial, você explorará as permissões do Django REST Framework e aprenderá como definir uma classe de permissão personalizada para o projeto de lista de tarefas.
Introdução às permissões do Django REST Framework
Django REST Framework possui algumas configurações de permissão integradas que você pode usar para proteger a API. Django REST Framework permite que você defina as permissões em três níveis:
- Nível do projeto
- Nível de visualização
- Nível de modelo
Permissões em nível de projeto
As permissões em nível de projeto são definidas na configuração única do Django chamada REST_FRAMEWORK
no settings.py
arquivo do projeto Django.
Por padrão, o Django REST Framework permite acesso irrestrito à API. É equivalente ao seguinte:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
]
}
Linguagem de código: Python ( python )
Além AllowAny
das classes de permissão, o Django REST Framework também oferece outras permissões integradas em nível de projeto:
IsAuthenticated
: apenas usuários autenticados têm acesso.IsAdminUser
: apenas os administradores/superusuários têm acesso.IsAuthenticatedOrReadOnly
: usuários não autenticados podem chamar qualquer API, mas apenas usuários autenticados precisam criar, atualizar e excluir privilégios.
Vamos usar a IsAuthenticated
classe de permissão:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
Linguagem de código: Python ( python )
Se você sair como superusuário e acessar o endpoint da API que mostra todos os todos /api/v1/todos/
, receberá a seguinte mensagem de erro HTTP 403 proibido:
HTTP 403 Forbidden
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"detail": "Authentication credentials were not provided."
}
Linguagem de código: Python ( python )
O motivo é que a API requer usuário autenticado.
Vamos criar um usuário normal chamado testapi
usando o site de administração http://localhost:8000/admin/1
. Observe que um usuário normal não é um superusuário.
Para permitir que o usuário normal testapi
faça login e logout, você precisa atualizar o URLconf no nível do projeto para criar as visualizações de login/logout:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include('api.urls')),
path("auth/", include("rest_framework.urls")), # added
]
Linguagem de código: Python ( python )
Depois de rest_framework.urls
definido, você pode acessar o endpoint da API /api/v1/todos/
. Uma pequena alteração é o link de login no lado direito:
Se você clicar no link Login, verá o formulário de login da seguinte forma:
Faça login na API navegável usando um usuário testapi
e uma senha normais. Depois de fazer login com sucesso com o testapi
usuário, você verá a seguinte resposta:
Permissões no nível da visualização
Django REST Framework permite adicionar permissões no nível de visualização para um controle mais granular.
Por exemplo, você pode atualizar a TodoDetail
visualização para que apenas usuários administradores possam visualizá-la, mas usuários normais não possam acessá-la.
class TodoDetail(generics.RetrieveUpdateDestroyAPIView):
permission_classes = (permissions.IsAdminUser,) # added
queryset = Todo.objects.all()
serializer_class = TodoSerializer
Linguagem de código: Python ( python )
A
visualização tem o TodoDetail
permission_classes
que é inicializado para o arquivo permissions.IsAdminUser
.
Ao fazer isso, o Django REST Framework permite apenas que o usuário administrador acesse a
visualização, que mapeia para o endpoint da API TodoDetail
/api/v1/todos/id
.
Se você usar o testapi
usuário (usuário normal) para acessar a API Todo detail, o HTTP 403 será proibido:
Para desconectar o testapi
usuário, clique no link do nome de usuário e selecione clicar no link de logout:
E faça login na API navegável usando o superadministrador ( john
).
Como a TodoDetail
visualização permite o acesso do superadministrador, você pode ver a resposta da API:
Permissões personalizadas
No projeto Todo, você pode restringir o acesso para que apenas os proprietários de todos possam visualizar, editar, atualizar e excluir. Mas eles não podem acessar todos os outros usuários. Além disso, o superusuário terá acesso à sua própria lista de tarefas, bem como gerenciará as tarefas de outros usuários.
Para acomodar esses requisitos de permissão, você precisa usar as permissões personalizadas do Django REST Framework.
Para definir permissão customizada, você usa a BasePermission
classe do Django REST Framework. Aqui está o código fonte da BasePermission
classe:
class BasePermission(metaclass=BasePermissionMetaclass):
"""
A base class from which all permission classes should inherit.
"""
def has_permission(self, request, view):
"""
Return `True` if permission is granted, `False` otherwise.
"""
return True
def has_object_permission(self, request, view, obj):
"""
Return `True` if permission is granted, `False` otherwise.
"""
return True
Linguagem de código: Python ( python )
O BasePermission
tem dois métodos:
has_permission(self, request, view)
– RetornarTrue
se a permissão for concedida ouFalse
não. As visualizações de lista chamarão o
método para verificar as permissões.has_permission
has_object_permission(self, requests, view, obj)
– RetornarTrue
se a permissão for concedida ouFalse
não. O método de visualização detalhada será chamadohas_permission()
primeiro. Se for aprovado, ele chamará o
método next para verificar as permissões.has_object_permission
()
É uma boa prática substituir ambos os métodos explicitamente para evitar configurações padrão indesejadas da classe base.
A seguir ilustramos as etapas para definir e usar uma classe de permissão personalizada no Django REST Framework:
Primeiro, defina a IsOwnerOnly
classe que estende a BasePermission
classe no permissions.py
arquivo:
from rest_framework import permissions
class IsOwnerOnly(permissions.BasePermission):
def has_permission(self, request, view):
return True
def has_object_permission(self, request, view, obj):
if request.user.is_superuser:
return True
return obj.user == request.user
Linguagem de código: Python ( python )
O has_permission
sempre retorna True
. Isso significa que qualquer usuário pode acessar a TodoList
visualização para obter todas as tarefas e criar uma nova tarefa. Observe que para restringir o acesso a todos do usuário atual, faremos isso na TodoList
visualização mais tarde.
O has_object_permission
método retorna True
se o usuário atual for o superusuário ou o proprietário da tarefa.
Segundo, atualize as classes de visualização no views.py
aplicativo api
para usar a classe de permissão personalizada IsOwnerOnly
:
from rest_framework import generics
from .serializers import TodoSerializer
from .permissions import IsOwnerOnly
from todo.models import Todo
class TodoList(generics.ListCreateAPIView):
permission_classes = (IsOwnerOnly,) # added
queryset = Todo.objects.all()
serializer_class = TodoSerializer
def perform_create(self, serializer):
serializer.save(user=self.request.user)
# added
def filter_queryset(self, queryset):
queryset = queryset.filter(user=self.request.user)
return super().filter_queryset(queryset)
class TodoDetail(generics.RetrieveUpdateDestroyAPIView):
permission_classes = (IsOwnerOnly,) # added
queryset = Todo.objects.all()
serializer_class = TodoSerializer
Linguagem de código: Python ( python )
Ambas TodoList
as TodoDetail
classes e usam a IsOwnerOnly
classe:
permission_classes = (IsOwnerOnly,) # added
Linguagem de código: Python ( python )
Além disso, adicione o filter_queryset
método à TodoList
classe para retornar apenas todos do usuário atualmente autenticado:
def filter_queryset(self, queryset):
queryset = queryset.filter(user=self.request.user)
return super().filter_queryset(queryset)
Linguagem de código: Python ( python )
Se você fizer login na API navegável usando o superusuário, poderá visualizar, criar, editar, atualizar e excluir todos.
Mas se você fizer login usando o usuário normal ( testapi
), poderá ver que ele /api/v1/todos/
retorna uma lista vazia.
Além disso, acessar o endpoint da API /api/v1/todos/1/
resultará em um HTTP 403 proibido, pois o testapi
usuário não tem acesso à tarefa que não pertence ao usuário:
Agora, você pode usar o testapi
usuário para criar uma nova tarefa com as seguintes informações:
{
"title": "Test API",
"completed": false
}
Linguagem de código: Python ( python )
Aqui está a resposta:
HTTP 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"id": 5,
"title": "Test API",
"completed": false,
"user": "testapi"
}
Linguagem de código: Python ( python )
Faça uma solicitação HTTP GET para o /api/v1/todos/
endpoint, você obterá a lista de tarefas criada pelo testapi
usuário:
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
[
{
"id": 5,
"title": "Test API",
"completed": false,
"user": "testapi"
}
]
Linguagem de código: Python ( python )
Além disso, você pode testar a visualização, atualização e exclusão de tarefas com id 5 usando o testapi
usuário. Deve funcionar conforme o esperado.
Baixe o código fonte do projeto
Clique no link a seguir para baixar o código-fonte do projeto:
Baixe o código fonte do projeto
Resumo
- Django REST Framework fornece três níveis de permissão, incluindo nível de projeto, nível de visualização e nível de modelo.
- Estenda a
BasePermisssion
classe para definir permissões personalizadas de acordo com seus requisitos.