Autenticazione API
Lâautenticazione eâ un aspetto fondamentale di qualsiasi API. Django REST Framework offre diversi sistemi di autenticazione e un framework di permessi flessibile per controllare lâaccesso alle risorse.
TokenAuthentication
Lâautenticazione basata su token eâ uno dei metodi piuâ utilizzati per le API. Ogni utente riceve un token unico che deve includere in ogni richiesta.
# settings.py
INSTALLED_APPS = [
# ...
'rest_framework',
'rest_framework.authtoken', # Aggiungi questa app
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
],
}
Dopo aver aggiunto lâapp, esegui le migrazioni e crea i token:
# Esegui le migrazioni
# python manage.py migrate
# Creare un token per un utente
from rest_framework.authtoken.models import Token
from django.contrib.auth.models import User
utente = User.objects.get(username='mario')
token, created = Token.objects.get_or_create(user=utente)
print(token.key) # Il token da usare nelle richieste
Per creare un endpoint di login che restituisce il token:
# views.py
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
class LoginView(ObtainAuthToken):
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
utente = serializer.validated_data['user']
token, created = Token.objects.get_or_create(user=utente)
return Response({
'token': token.key,
'user_id': utente.pk,
'email': utente.email,
})
Il client invia il token nellâheader Authorization:
# Header della richiesta HTTP:
# Authorization: Token abc123tokenLungo456
SessionAuthentication
Lâautenticazione basata su sessione utilizza il sistema di sessioni di Django. Eâ ideale per le applicazioni web dove il frontend e il backend condividono lo stesso dominio.
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
],
}
Con SessionAuthentication, le richieste POST richiedono il token CSRF. Questo metodo eâ adatto quando lâAPI viene consumata da pagine HTML servite dallo stesso progetto Django.
JWT con djangorestframework-simplejwt
JSON Web Token (JWT) eâ uno standard moderno per lâautenticazione stateless. Il pacchetto djangorestframework-simplejwt fornisce unâimplementazione completa.
# Installazione
# pip install djangorestframework-simplejwt
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
}
from datetime import timedelta
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
'AUTH_HEADER_TYPES': ('Bearer',),
}
Configura le URL per ottenere e rinnovare i token JWT:
# urls.py
from django.urls import path
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
Il client invia il token JWT nellâheader:
# Header della richiesta HTTP:
# Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
Classi di Permesso
DRF include diverse classi di permesso per controllare chi puoâ accedere alle risorse.
IsAuthenticated
Permette lâaccesso solo agli utenti autenticati:
from rest_framework.permissions import IsAuthenticated
class LibroViewSet(viewsets.ModelViewSet):
queryset = Libro.objects.all()
serializer_class = LibroSerializer
permission_classes = [IsAuthenticated]
IsAdminUser
Permette lâaccesso solo agli utenti con is_staff = True:
from rest_framework.permissions import IsAdminUser
class GestioneUtentiView(APIView):
permission_classes = [IsAdminUser]
def get(self, request):
utenti = User.objects.all()
return Response(UtenteSerializer(utenti, many=True).data)
AllowAny
Permette lâaccesso a chiunque, senza autenticazione:
from rest_framework.permissions import AllowAny
class RegistrazioneView(APIView):
permission_classes = [AllowAny]
def post(self, request):
serializer = RegistrazioneSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response({'messaggio': 'Registrazione completata'}, status=201)
IsAuthenticatedOrReadOnly
Permette la lettura a tutti ma le modifiche solo agli utenti autenticati:
from rest_framework.permissions import IsAuthenticatedOrReadOnly
class ArticoloViewSet(viewsets.ModelViewSet):
queryset = Articolo.objects.all()
serializer_class = ArticoloSerializer
permission_classes = [IsAuthenticatedOrReadOnly]
Permessi Personalizzati
Puoi creare classi di permesso personalizzate per logiche di autorizzazione specifiche.
from rest_framework.permissions import BasePermission
class IsProprietario(BasePermission):
"""Permette l'accesso solo al proprietario dell'oggetto."""
def has_object_permission(self, request, view, obj):
return obj.proprietario == request.user
class IsProprietarioOSolaLettura(BasePermission):
"""Lettura per tutti, modifica solo per il proprietario."""
def has_object_permission(self, request, view, obj):
if request.method in ('GET', 'HEAD', 'OPTIONS'):
return True
return obj.proprietario == request.user
class LibroViewSet(viewsets.ModelViewSet):
queryset = Libro.objects.all()
serializer_class = LibroSerializer
permission_classes = [IsAuthenticated, IsProprietarioOSolaLettura]
Conclusione
Django REST Framework offre un ecosistema completo per lâautenticazione e lâautorizzazione delle API. Dalla semplicitaâ dei Token alla flessibilitaâ dei JWT, passando per le sessioni e i permessi personalizzati, DRF consente di proteggere le risorse in modo granulare e adattabile a qualsiasi esigenza applicativa. La combinazione di classi di autenticazione e permessi garantisce un controllo preciso su chi puoâ accedere e modificare i dati.