SÀkra dina Django REST Framework-API:er med robust autentisering. JÀmför Token-autentisering och JWT-implementering, inklusive praktiska kodexempel och bÀsta praxis.
Python DRF-autentisering: Token kontra JWT-implementering för robusta API:er
Att sÀkra dina API:er Àr av största vikt. NÀr du bygger API:er med Python och Django REST Framework (DRF) har du flera autentiseringsalternativ tillgÀngliga. Den hÀr artikeln gÄr in pÄ tvÄ populÀra metoder: Token-autentisering och JWT-autentisering (JSON Web Token), jÀmför deras styrkor och svagheter och ger praktiska implementeringsexempel.
FörstÄ autentisering i API:er
Autentisering Àr processen att verifiera identiteten hos en anvÀndare eller applikation som ansluter till ditt API. Ett vÀl implementerat autentiseringssystem sÀkerstÀller att endast behöriga entiteter kan komma Ät skyddade resurser. I samband med RESTful API:er innebÀr autentisering vanligtvis att autentiseringsuppgifter (t.ex. anvÀndarnamn och lösenord) skickas med varje begÀran. Servern verifierar sedan dessa uppgifter och ger, om de Àr giltiga, Ätkomst.
Token-autentisering
Token-autentisering Àr en enkel och okomplicerad mekanism. NÀr en anvÀndare loggar in genererar servern en unik, slumpmÀssig token och lagrar den i databasen och associerar den med anvÀndaren. Klienten skickar sedan denna token i 'Authorization'-huvudet för efterföljande förfrÄgningar. Servern hÀmtar token frÄn databasen, verifierar dess giltighet och ger Ätkomst i enlighet dÀrmed.
Implementering med DRF
DRF har inbyggt stöd för Token-autentisering. SÄ hÀr implementerar du det:
- Installera DRF och registrera det i ditt Django-projekt:
Se först till att du har Django REST Framework installerat:
pip install djangorestframework
LĂ€gg sedan till det i dina `INSTALLED_APPS` i `settings.py`:
INSTALLED_APPS = [
...
'rest_framework',
]
- LĂ€gg till TokenAuthentication-schemat som en standardautentiseringsklass (valfritt, men rekommenderas):
LÀgg till följande i din `settings.py`-fil:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
}
Detta kommer att tillÀmpa Token-autentisering globalt över hela ditt API. `SessionAuthentication` ingÄr för webblÀsarbaserad interaktion, men du kan ta bort det för en helt API-driven applikation.
- Skapa en Token för varje anvÀndare:
Du kan automatiskt skapa tokens för anvÀndare vid skapandet genom att lÀgga till en signalhanterare. Skapa en fil med namnet `signals.py` i din app (t.ex. `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)
Importera sedan den hÀr `signals.py`-filen i din `users/apps.py`-fil inom `ready`-metoden i din appkonfigurationsklass. Exempel för `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 hantera tokes med kommandoraden:
python manage.py drf_create_token <username>
- Implementera dina API-vyer:
HÀr Àr ett enkelt exempel pÄ en vy som krÀver Token-autentisering:
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': 'Hello, ' + request.user.username + '! You are authenticated.',
}
return Response(content)
I det hÀr exemplet anger `authentication_classes` att Token-autentisering ska anvÀndas, och `permission_classes` anger att endast autentiserade anvÀndare kan komma Ät vyn.
- Inkludera API-vy för inloggning:
Du behöver ocksÄ en slutpunkt för att skapa token vid lyckad inloggning:
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': 'Invalid Credentials'}, status=status.HTTP_401_UNAUTHORIZED)
Fördelar med Token-autentisering
- Enkelhet: LÀtt att implementera och förstÄ.
- TillstÄndslös: Varje token-begÀran innehÄller information som gör att den kan stÄ ensam.
Nackdelar med Token-autentisering
- Databasberoende: KrÀver en databasuppslagning för varje begÀran för att validera token. Detta kan pÄverka prestandan, sÀrskilt i stor skala.
- à terkallande av token: Att Äterkalla en token krÀver att den raderas frÄn databasen, vilket kan vara komplext.
- Skalbarhet: Kanske inte den mest skalbara lösningen för stora API:er med hög trafik pÄ grund av databasomkostnaderna.
JWT-autentisering (JSON Web Token)
JWT-autentisering Àr ett modernare och mer sofistikerat tillvÀgagÄngssÀtt. En JWT Àr ett kompakt, URL-sÀkert JSON-objekt som innehÄller ansprÄk om anvÀndaren. Dessa ansprÄk Àr digitalt signerade med en hemlig nyckel eller ett offentligt/privat nyckelpar. NÀr en anvÀndare loggar in genererar servern en JWT och skickar den till klienten. Klienten inkluderar sedan denna JWT i 'Authorization'-huvudet för efterföljande förfrÄgningar. Servern kan verifiera JWT:s signatur utan att behöva komma Ät en databas, vilket gör det till en mer effektiv och skalbar lösning.
Implementering med DRF
DRF har inte inbyggt stöd för JWT-autentisering, men flera utmÀrkta bibliotek gör det enkelt att integrera. Ett av de mest populÀra Àr `djangorestframework-simplejwt`.
- Installera `djangorestframework-simplejwt`:
pip install djangorestframework-simplejwt
- Konfigurera DRF-instÀllningar:
LÀgg till följande i din `settings.py`-fil:
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',
}
Förklaring av instÀllningar:
- `ACCESS_TOKEN_LIFETIME`: Hur lÀnge Ätkomsttoken Àr giltig (exempel, 5 minuter).
- `REFRESH_TOKEN_LIFETIME`: Hur lÀnge uppdateringstoken Àr giltig (exempel, 1 dag). Uppdateringstokens anvÀnds för att erhÄlla nya Ätkomsttokens utan att krÀva att anvÀndaren loggar in igen.
- `ROTATE_REFRESH_TOKENS`: Om uppdateringstokens ska roteras efter varje anvÀndning.
- `BLACKLIST_AFTER_ROTATION`: Om gamla uppdateringstokens ska svartlistas efter rotation.
- `ALGORITHM`: Algoritmen som anvÀnds för att signera JWT (HS256 Àr ett vanligt val).
- `SIGNING_KEY`: Den hemliga nyckeln som anvÀnds för att signera JWT (vanligtvis din Django SECRET_KEY).
- `AUTH_HEADER_TYPES`: Typen av auktoriseringshuvud (vanligtvis "Bearer").
- Inkludera API-vyer för inloggning och uppdatering av token:
`djangorestframework-simplejwt` tillhandahÄller vyer för att erhÄlla och uppdatera tokens. Inkludera 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` ger Ätkomst och uppdateringstokens efter lyckad autentisering. `TokenRefreshView` ger en ny Ätkomsttoken nÀr den tillhandahÄlls med en giltig uppdateringstoken.
- Implementera dina API-vyer:
HÀr Àr ett enkelt exempel pÄ en vy som krÀver JWT-autentisering:
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': 'Hello, ' + request.user.username + '! You are authenticated.',
}
return Response(content)
I likhet med Token-autentiseringsexemplet anger `authentication_classes` att JWT-autentisering ska anvÀndas, och `permission_classes` begrÀnsar Ätkomsten till endast autentiserade anvÀndare.
Fördelar med JWT-autentisering
- Skalbarhet: Ingen databasuppslagning krÀvs för tokenvalidering, vilket gör den mer skalbar.
- TillstÄndslös: JWT innehÄller all nödvÀndig information för autentisering.
- Standardiserad: JWT Àr en allmÀnt vedertagen standard som stöds av mÄnga bibliotek och plattformar.
- MikrotjÀnstevÀnlig: LÀmplig för mikrotjÀnstarkitekturer, eftersom tjÀnster oberoende kan verifiera JWT:er.
Nackdelar med JWT-autentisering
- Komplexitet: Mer komplex att implementera Àn Token-autentisering.
- Tokenstorlek: JWT:er kan vara större Àn enkla tokens, vilket potentiellt ökar bandbreddsanvÀndningen.
- à terkallande av token: Att Äterkalla en JWT Àr utmanande. NÀr den vÀl har utfÀrdats Àr den giltig fram till dess utgÄng. Lösningar involverar svartlistning av Äterkallade tokens, vilket Äterinför databasberoende.
Strategier för Äterkallande av token
BÄde Token- och JWT-autentiseringsmetoder krÀver mekanismer för att Äterkalla Ätkomst. SÄ hÀr kan du nÀrma dig Äterkallande av token:
Ă terkallande av Token-autentisering
Med Token-autentisering Àr Äterkallande okomplicerat: radera helt enkelt token frÄn databasen:
from rest_framework.authtoken.models import Token
try:
token = Token.objects.get(user=request.user)
token.delete()
except Token.DoesNotExist:
pass
Ă terkallande av JWT-autentisering
JWT-Äterkallande Àr mer komplext eftersom token i sig Àr fristÄende och inte förlitar sig pÄ en databasuppslagning för validering (initialt). Vanliga strategier inkluderar:
- Svartlistning av token: Lagra Äterkallade tokens i en svartlista (t.ex. en databastabell eller en Redis-cache). Innan du validerar en JWT, kontrollera om den finns i svartlistan. `djangorestframework-simplejwt` har inbyggt stöd för svartlistning av uppdateringstokens.
- Korta utgÄngstider: AnvÀnd korta utgÄngstider för Ätkomsttokens och förlita dig pÄ uppdateringstokens för att erhÄlla nya Ätkomsttokens ofta. Detta begrÀnsar möjlighetsfönstret för en komprometterad token att anvÀndas.
- Rotera uppdateringstokens: Rotera uppdateringstokens efter varje anvÀndning. Detta kommer att ogiltigförklara gamla tokens varje gÄng och förhindra tokenstöld.
OAuth2 och OpenID Connect
För mer komplexa autentiserings- och auktoriseringsscenarier, övervÀg att anvÀnda OAuth2 och OpenID Connect. Dessa standarder tillhandahÄller ett robust ramverk för att delegera Ätkomst till resurser utan att dela autentiseringsuppgifter. OAuth2 Àr frÀmst ett auktoriseringsprotokoll, medan OpenID Connect bygger pÄ OAuth2 för att tillhandahÄlla autentiseringstjÀnster. Flera Django-paket, sÄsom `django-oauth-toolkit` och `django-allauth`, underlÀttar integrationen av OAuth2 och OpenID Connect i dina DRF-API:er.
Exempelscenario: En anvÀndare vill ge en tredje parts applikation Ätkomst till sina data som lagras i ditt API. Med OAuth2 kan anvÀndaren auktorisera applikationen utan att dela sitt anvÀndarnamn och lösenord. IstÀllet fÄr applikationen en Ätkomsttoken som den kan anvÀnda för att komma Ät anvÀndarens data inom den definierade behörighetsomfattningen.
VÀlja rÀtt autentiseringsmetod
Den bÀsta autentiseringsmetoden beror pÄ dina specifika krav:
- Enkelhet och implementeringshastighet: Token-autentisering Àr generellt sett lÀttare att implementera initialt.
- Skalbarhet: JWT-autentisering Àr mer skalbar för API:er med hög trafik.
- SÀkerhetskrav: TÀnk pÄ kÀnsligheten hos dina data och den sÀkerhetsnivÄ som krÀvs. OAuth2/OpenID Connect erbjuder de mest robusta sÀkerhetsfunktionerna men krÀver mer komplex implementering.
- MikrotjÀnstarkitektur: JWT:er Àr vÀl lÀmpade för mikrotjÀnster, eftersom varje tjÀnst oberoende kan verifiera tokens.
BÀsta praxis för API-autentisering
- AnvÀnd HTTPS: AnvÀnd alltid HTTPS för att kryptera kommunikationen mellan klienten och servern, vilket skyddar autentiseringsuppgifter frÄn avlyssning.
- Lagra hemligheter sÀkert: Lagra aldrig hemliga nycklar eller lösenord i klartext. AnvÀnd miljövariabler eller sÀkra verktyg för konfigurationshantering.
- Implementera hastighetsbegrÀnsning: Skydda ditt API frÄn missbruk genom att implementera hastighetsbegrÀnsning för att begrÀnsa antalet förfrÄgningar som en klient kan göra inom en given tidsperiod.
- Validera indata: Validera noggrant all indata för att förhindra injektionsattacker.
- Ăvervaka och logga: Ăvervaka ditt API för misstĂ€nkt aktivitet och logga autentiseringshĂ€ndelser för granskningsĂ€ndamĂ„l.
- Uppdatera bibliotek regelbundet: HÄll dina Django-, DRF- och autentiseringsbibliotek uppdaterade för att dra nytta av sÀkerhetskorrigeringar och förbÀttringar.
- Implementera CORS (Cross-Origin Resource Sharing): Konfigurera CORS korrekt för att tillÄta att endast betrodda domÀner fÄr Ätkomst till ditt API frÄn webblÀsare.
Slutsats
Att vÀlja lÀmplig autentiseringsmetod Àr avgörande för att sÀkra dina DRF-API:er. Token-autentisering erbjuder enkelhet, medan JWT-autentisering ger skalbarhet och flexibilitet. Att förstÄ fördelarna och nackdelarna med varje metod, tillsammans med bÀsta praxis för API-sÀkerhet, gör att du kan bygga robusta och sÀkra API:er som skyddar dina data och anvÀndare.
Kom ihÄg att övervÀga dina specifika behov och vÀlj den lösning som bÀst balanserar sÀkerhet, prestanda och enkel implementering. Utforska OAuth2 och OpenID Connect för mer komplexa auktoriseringsscenarier.