Sikre dine Django REST Framework API'er med robust godkendelse. Sammenlign Token-godkendelse og JWT-implementering.
Python DRF-godkendelse: Token vs. JWT-implementering til robuste API'er
Sikring af dine API'er er altafgørende. Når du bygger API'er med Python og Django REST Framework (DRF), har du flere godkendelsesmuligheder tilgængelige. Denne artikel dykker ned i to populære metoder: Token-godkendelse og JWT (JSON Web Token) godkendelse, hvor vi sammenligner deres styrker og svagheder og giver praktiske implementeringseksempler.
Forståelse af godkendelse i API'er
Godkendelse er processen med at verificere identiteten af en bruger eller applikation, der tilgår din API. Et velfungerende godkendelsessystem sikrer, at kun autoriserede enheder kan få adgang til beskyttede ressourcer. I forbindelse med RESTful API'er involverer godkendelse typisk at sende legitimationsoplysninger (f.eks. brugernavn og adgangskode) med hver anmodning. Serveren verificerer derefter disse legitimationsoplysninger og giver adgang, hvis de er gyldige.
Token-godkendelse
Token-godkendelse er en enkel og ligetil mekanisme. Når en bruger logger succesfuldt ind, genererer serveren et unikt, tilfældigt token og gemmer det i databasen, forbundet med brugeren. Klienten sender derefter dette token i 'Authorization'-headeren af efterfølgende anmodninger. Serveren henter tokenet fra databasen, verificerer dets gyldighed og giver adgang i overensstemmelse hermed.
Implementering med DRF
DRF giver indbygget understøttelse af Token-godkendelse. Her er, hvordan du implementerer det:
- Installer DRF og registrer det i dit Django-projekt:
Først skal du sikre dig, at du har Django REST Framework installeret:
pip install djangorestframework
Tilføj det derefter til din `INSTALLED_APPS` i `settings.py`:
INSTALLED_APPS = [
...
'rest_framework',
]
- Tilføj TokenAuthentication-skemaet som en standard-godkendelsesklasse (valgfrit, men anbefales):
I din `settings.py`-fil skal du tilføje følgende:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
}
Dette vil anvende Token-godkendelse globalt på tværs af din API. `SessionAuthentication` er inkluderet til browserbaseret interaktion, men du kan fjerne den for en rent API-drevet applikation.
- Opret et token for hver bruger:
Du kan automatisk oprette tokens for brugere ved oprettelse ved at tilføje en signalhåndtering. Opret en fil ved navn `signals.py` i din app (f.eks. `users/signals.py`):
from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
Importer derefter denne `signals.py`-fil i din `users/apps.py`-fil inden i `ready`-metoden af din app-konfigurationsklasse. Eksempel for `users/apps.py`:
from django.apps import AppConfig
class UsersConfig(AppConfig):
default_auto_field = 'django.db.BigAutoField'
name = 'users'
def ready(self):
import users.signals
Nu kan du administrere tokens ved hjælp af kommandolinjen:
python manage.py drf_create_token <brugernavn>
- Implementer dine API-visninger:
Her er et simpelt eksempel på en visning, der kræver Token-godkendelse:
from rest_framework import permissions
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
authentication_classes = [TokenAuthentication]
permission_classes = [permissions.IsAuthenticated]
def get(self, request):
content = {
'message': 'Hej, ' + request.user.username + '! Du er godkendt.',
}
return Response(content)
I dette eksempel angiver `authentication_classes`, at Token-godkendelse skal bruges, og `permission_classes` angiver, at kun godkendte brugere kan få adgang til visningen.
- Inkluder Login API-visning:
Du har også brug for et endpoint til at oprette tokenet ved succesfuld login:
from django.contrib.auth import authenticate
from rest_framework import status
from rest_framework.authtoken.models import Token
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
@api_view(['POST'])
@permission_classes([AllowAny])
def login(request):
username = request.data.get('username')
password = request.data.get('password')
user = authenticate(username=username, password=password)
if user:
token, _ = Token.objects.get_or_create(user=user)
return Response({'token': token.key})
else:
return Response({'error': 'Ugyldige legitimationsoplysninger'}, status=status.HTTP_401_UNAUTHORIZED)
Fordele ved Token-godkendelse
- Enkelhed: Let at implementere og forstå.
- Stateless: Hver tokenanmodning indeholder oplysninger, der gør, at den kan stå alene.
Ulemper ved Token-godkendelse
- Databaseafhængighed: Kræver et opslag i databasen for hver anmodning for at validere tokenet. Dette kan påvirke ydeevnen, især i stor skala.
- Token tilbagekaldelse: Tilbagekaldelse af et token kræver sletning af det fra databasen, hvilket kan være komplekst.
- Skalerbarhed: Måske ikke den mest skalerbare løsning for store API'er med høj trafik på grund af database-overhead.
JWT (JSON Web Token) godkendelse
JWT-godkendelse er en mere moderne og sofistikeret tilgang. En JWT er et kompakt, URL-sikkert JSON-objekt, der indeholder påstande om brugeren. Disse påstande er digitalt signeret ved hjælp af en hemmelig nøgle eller et offentligt/privat nøglepar. Når en bruger logger ind, genererer serveren en JWT og sender den til klienten. Klienten inkluderer derefter denne JWT i 'Authorization'-headeren af efterfølgende anmodninger. Serveren kan verificere JWT'ens signatur uden at skulle tilgå en database, hvilket gør det til en mere effektiv og skalerbar løsning.
Implementering med DRF
DRF giver ikke indbygget understøttelse af JWT-godkendelse, men flere fremragende biblioteker gør det nemt at integrere. Et af de mest populære er `djangorestframework-simplejwt`.
- Installer ` djangorestframework-simplejwt`:
pip install djangorestframework-simplejwt
- Konfigurer DRF-indstillinger:
I din `settings.py`-fil skal du tilføje følgende:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': True,
'ALGORITHM': 'HS256',
'SIGNING_KEY': settings.SECRET_KEY,
'VERIFYING_KEY': None,
'AUTH_HEADER_TYPES': ('Bearer',),
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
}
Forklaring af indstillinger:
- `ACCESS_TOKEN_LIFETIME`: Hvor længe adgangstokenet er gyldigt (eksempelvis 5 minutter).
- `REFRESH_TOKEN_LIFETIME`: Hvor længe fornyelsestokenet er gyldigt (eksempelvis 1 dag). Fornyelsestokens bruges til at opnå nye adgangstokens uden at kræve, at brugeren logger ind igen.
- `ROTATE_REFRESH_TOKENS`: Om fornyelsestokens skal roteres efter hver brug.
- `BLACKLIST_AFTER_ROTATION`: Om gamle fornyelsestokens skal sortlistes efter rotation.
- `ALGORITHM`: Algoritmen, der bruges til at signere JWT'en (HS256 er et almindeligt valg).
- `SIGNING_KEY`: Den hemmelige nøgle, der bruges til at signere JWT'en (typisk din Django SECRET_KEY).
- `AUTH_HEADER_TYPES`: Typen af godkendelsesheader (typisk "Bearer").
- Inkluder Login- og Fornyelsestoken API-visninger:
` djangorestframework-simplejwt` leverer visninger til at opnå og forny tokens. Inkluder dem i din `urls.py`:
from django.urls import path
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
`TokenObtainPairView` leverer adgangs- og fornyelsestokens efter succesfuld godkendelse. `TokenRefreshView` leverer et nyt adgangstoken, når det forsynes med et gyldigt fornyelsestoken.
- Implementer dine API-visninger:
Her er et simpelt eksempel på en visning, der kræver JWT-godkendelse:
from rest_framework import permissions
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_simplejwt.authentication import JWTAuthentication
class ExampleView(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [permissions.IsAuthenticated]
def get(self, request):
content = {
'message': 'Hej, ' + request.user.username + '! Du er godkendt.',
}
return Response(content)
Ligesom i Token-godkendelseseksemplet angiver `authentication_classes`, at JWT-godkendelse skal bruges, og `permission_classes` begrænser adgangen til kun godkendte brugere.
Fordele ved JWT-godkendelse
- Skalerbarhed: Ingen databaseopslag er nødvendig for tokenvalidering, hvilket gør det mere skalerbart.
- Stateless: JWT'en indeholder alle nødvendige oplysninger til godkendelse.
- Standardiseret: JWT er en bredt adopteret standard, der understøttes af mange biblioteker og platforme.
- Venlig over for microservices: Velegnet til microservices-arkitekturer, da tjenester uafhængigt kan verificere JWT'er.
Ulemper ved JWT-godkendelse
- Kompleksitet: Mere kompleks at implementere end Token-godkendelse.
- Tokenstørrelse: JWT'er kan være større end simple tokens, hvilket potentielt øger båndbreddebrug.
- Token tilbagekaldelse: Tilbagekaldelse af en JWT er udfordrende. Når den er udstedt, er den gyldig indtil udløb. Løsninger involverer sortlistning af tilbagekaldte tokens, hvilket genintroducerer databaseafhængighed.
Strategier for token tilbagekaldelse
Både Token- og JWT-godkendelsesmetoder kræver mekanismer til tilbagekaldelse af adgang. Her er, hvordan du kan gribe token tilbagekaldelse an:
Token-godkendelses tilbagekaldelse
Med Token-godkendelse er tilbagekaldelse ligetil: slet blot tokenet fra databasen:
from rest_framework.authtoken.models import Token
try:
token = Token.objects.get(user=request.user)
token.delete()
except Token.DoesNotExist:
pass
JWT-godkendelses tilbagekaldelse
JWT-tilbagekaldelse er mere kompleks, fordi tokenet i sig selv er selvstændigt og ikke afhænger af et databaseopslag for validering (indledningsvis). Almindelige strategier inkluderer:
- Token sortlistning: Gem tilbagekaldte tokens i en sortliste (f.eks. en databasetabel eller et Redis-cache). Før du validerer en JWT, skal du kontrollere, om den er på sortlisten. `djangorestframework-simplejwt` tilbyder indbygget understøttelse af sortlistning af fornyelsestokens.
- Korte udløbstider: Brug korte udløbstider for adgangstokens, og stol på fornyelsestokens for at opnå nye adgangstokens hyppigt. Dette begrænser mulighedernes vindue for et kompromitteret token til at blive brugt.
- Roter fornyelsestokens: Roter fornyelsestokens efter hver brug. Dette vil ugyldiggøre gamle tokens hver gang og forhindre token-tyveri.
OAuth2 og OpenID Connect
For mere komplekse godkendelses- og autorisationsscenarier, overvej at bruge OAuth2 og OpenID Connect. Disse standarder giver et robust framework til at delegere adgang til ressourcer uden at dele legitimationsoplysninger. OAuth2 er primært en autorisationsprotokol, mens OpenID Connect bygger på OAuth2 for at levere godkendelsestjenester. Flere Django-pakker, såsom `django-oauth-toolkit` og `django-allauth`, letter integrationen af OAuth2 og OpenID Connect i dine DRF API'er.
Eksempel-scenarie: En bruger ønsker at give en tredjepartsapplikation adgang til deres data gemt i din API. Med OAuth2 kan brugeren godkende applikationen uden at dele sit brugernavn og adgangskode. I stedet modtager applikationen et adgangstoken, som den kan bruge til at få adgang til brugerens data inden for det definerede omfang af tilladelser.
Valg af den rigtige godkendelsesmetode
Den bedste godkendelsesmetode afhænger af dine specifikke krav:
- Enkelhed og hastighed af implementering: Token-godkendelse er generelt lettere at implementere indledningsvis.
- Skalerbarhed: JWT-godkendelse er mere skalerbar for API'er med høj trafik.
- Sikkerhedskrav: Overvej følsomheden af dine data og det krævede sikkerhedsniveau. OAuth2/OpenID Connect tilbyder de mest robuste sikkerhedsfunktioner, men kræver mere kompleks implementering.
- Microservices-arkitektur: JWT'er er velegnede til microservices, da hver tjeneste uafhængigt kan verificere tokens.
Bedste praksis for API-godkendelse
- Brug HTTPS: Brug altid HTTPS til at kryptere kommunikationen mellem klienten og serveren, hvilket beskytter legitimationsoplysninger mod aflytning.
- Gem hemmeligheder sikkert: Gem aldrig hemmelige nøgler eller adgangskoder i klartekst. Brug miljøvariabler eller sikre konfigurationsstyringsværktøjer.
- Implementer rate limiting: Beskyt din API mod misbrug ved at implementere rate limiting for at begrænse antallet af anmodninger, en klient kan foretage inden for en given tidsperiode.
- Valider input: Valider alle inputdata grundigt for at forhindre injection-angreb.
- Overvåg og log: Overvåg din API for mistænkelig aktivitet og log godkendelseshændelser til revisionsformål.
- Opdater biblioteker regelmæssigt: Hold dine Django-, DRF- og godkendelsesbiblioteker opdaterede for at drage fordel af sikkerhedsopdateringer og forbedringer.
- Implementer CORS (Cross-Origin Resource Sharing): Konfigurer CORS korrekt for kun at tillade betroede domæner at få adgang til din API fra webbrowsere.
Konklusion
Valg af den passende godkendelsesmetode er afgørende for at sikre dine DRF API'er. Token-godkendelse tilbyder enkelhed, mens JWT-godkendelse giver skalerbarhed og fleksibilitet. Forståelse af fordele og ulemper ved hver metode, sammen med bedste praksis for API-sikkerhed, vil gøre dig i stand til at bygge robuste og sikre API'er, der beskytter dine data og brugere.
Husk at overveje dine specifikke behov og vælg den løsning, der bedst balancerer sikkerhed, ydeevne og implementeringslethed. Udforsk OAuth2 og OpenID Connect for mere komplekse autorisationsscenarier.