Suojaa Django REST Framework -API:si vankalla todennuksella. Vertaile tunnus- ja JWT-todennusta käytännön esimerkein ja parhaine käytäntöineen.
Python DRF -todennus: Tunnuksen ja JWT:n toteutus vankkoihin API-rajapintoihin
API-rajapintojen turvaaminen on ensiarvoisen tärkeää. Kun rakennat API-rajapintoja Pythonilla ja Django REST Frameworkilla (DRF), sinulla on useita todennusvaihtoehtoja. Tämä artikkeli syventyy kahteen suosittuun menetelmään: tunnus-todennukseen ja JWT (JSON Web Token) -todennukseen, vertaillen niiden vahvuuksia ja heikkouksia sekä tarjoten käytännön toteutusesimerkkejä.
Todennuksen ymmärtäminen API-rajapinnoissa
Todennus on prosessi, jossa tarkistetaan API-rajapintaasi käyttävän käyttäjän tai sovelluksen identiteetti. Hyvin toteutettu todennusjärjestelmä varmistaa, että vain valtuutetut tahot pääsevät käsiksi suojattuihin resursseihin. RESTful-API-rajapintojen yhteydessä todennus sisältää tyypillisesti tunnistetietojen (esim. käyttäjätunnus ja salasana) lähettämisen jokaisen pyynnön mukana. Palvelin tarkistaa nämä tunnistetiedot ja, jos ne ovat kelvollisia, myöntää pääsyn.
Tunnus-todennus
Tunnus-todennus on yksinkertainen ja suoraviivainen mekanismi. Kun käyttäjä kirjautuu onnistuneesti sisään, palvelin luo yksilöllisen, satunnaisen tunnuksen ja tallentaa sen tietokantaan yhdistäen sen käyttäjään. Asiakas lähettää tämän tunnuksen myöhempien pyyntöjen 'Authorization'-otsakkeessa. Palvelin hakee tunnuksen tietokannasta, tarkistaa sen kelpoisuuden ja myöntää pääsyn sen mukaisesti.
Toteutus DRF:llä
DRF tarjoaa sisäänrakennetun tuen tunnus-todennukselle. Näin se toteutetaan:
- Asenna DRF ja rekisteröi se Django-projektiisi:
Varmista ensin, että sinulla on Django REST Framework asennettuna:
pip install djangorestframework
Lisää se sitten `INSTALLED_APPS`-asetuksiin `settings.py`-tiedostossasi:
INSTALLED_APPS = [
...
'rest_framework',
]
- Lisää TokenAuthentication-skeema oletustodennusluokaksi (valinnainen, mutta suositeltava):
Lisää `settings.py`-tiedostoosi seuraava:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
}
Tämä soveltaa tunnus-todennusta globaalisti API-rajapintaasi. `SessionAuthentication` sisältyy selainpohjaiseen vuorovaikutukseen, mutta voit poistaa sen puhtaasti API-vetoisesta sovelluksesta.
- Luo tunnus jokaiselle käyttäjälle:
Voit luoda tunnuksia käyttäjille automaattisesti käyttäjän luonnin yhteydessä lisäämällä signaalin käsittelijän. Luo tiedosto nimeltä `signals.py` sovellukseesi (esim. `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)
Tuo sitten tämä `signals.py`-tiedosto `users/apps.py`-tiedostoosi sovelluksesi konfiguraatioluokan `ready`-metodin sisällä. Esimerkki `users/apps.py`:lle:
from django.apps import AppConfig
class UsersConfig(AppConfig):
default_auto_field = 'django.db.BigAutoField'
name = 'users'
def ready(self):
import users.signals
Nyt voit hallita tunnuksia komentoriviltä:
python manage.py drf_create_token <username>
- Toteuta API-näkymäsi:
Tässä yksinkertainen esimerkki näkymästä, joka vaatii tunnus-todennuksen:
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': 'Hei, ' + request.user.username + '! Olet todennettu.',
}
return Response(content)
Tässä esimerkissä `authentication_classes` määrittää, että tunnus-todennusta tulisi käyttää, ja `permission_classes` määrittää, että vain todennetut käyttäjät voivat käyttää näkymää.
- Sisällytä kirjautumisen API-näkymä:
Tarvitset myös päätepisteen tunnuksen luomiseen onnistuneen kirjautumisen yhteydessä:
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': 'Virheelliset tunnistetiedot'}, status=status.HTTP_401_UNAUTHORIZED)
Tunnus-todennuksen edut
- Yksinkertaisuus: Helppo toteuttaa ja ymmärtää.
- Tilaamaton: Jokainen tunnuspyyntö sisältää tiedot, jotka mahdollistavat sen itsenäisen toiminnan.
Tunnus-todennuksen haitat
- Tietokantariippuvuus: Vaatii tietokantahaun jokaiselle pyynnölle tunnuksen kelpoisuuden tarkistamiseksi. Tämä voi vaikuttaa suorituskykyyn, etenkin suuressa mittakaavassa.
- Tunnuksen peruuttaminen: Tunnuksen peruuttaminen edellyttää sen poistamista tietokannasta, mikä voi olla monimutkaista.
- Skaalautuvuus: Ei välttämättä ole skaalautuvin ratkaisu suurille, paljon liikennettä sisältäville API-rajapinnoille tietokannan ylikuormituksen vuoksi.
JWT (JSON Web Token) -todennus
JWT-todennus on modernimpi ja kehittyneempi lähestymistapa. JWT on kompakti, URL-turvallinen JSON-objekti, joka sisältää käyttäjää koskevia väitteitä. Nämä väitteet on digitaalisesti allekirjoitettu käyttämällä salaista avainta tai julkisen/yksityisen avaimen paria. Kun käyttäjä kirjautuu sisään, palvelin luo JWT:n ja lähettää sen asiakkaalle. Asiakas sisällyttää tämän JWT:n myöhempien pyyntöjen 'Authorization'-otsakkeeseen. Palvelin voi tarkistaa JWT:n allekirjoituksen ilman tietokantaa, mikä tekee siitä tehokkaamman ja skaalautuvamman ratkaisun.
Toteutus DRF:llä
DRF ei tarjoa sisäänrakennettua tukea JWT-todennukselle, mutta useat erinomaiset kirjastot tekevät sen integroinnista helppoa. Yksi suosituimmista on `djangorestframework-simplejwt`.
- Asenna `djangorestframework-simplejwt`:
pip install djangorestframework-simplejwt
- Määritä DRF-asetukset:
Lisää `settings.py`-tiedostoosi seuraava:
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',
}
Asetusten selitys:
- `ACCESS_TOKEN_LIFETIME`: Kuinka kauan pääsytunnus on voimassa (esimerkiksi 5 minuuttia).
- `REFRESH_TOKEN_LIFETIME`: Kuinka kauan päivitystunnus on voimassa (esimerkiksi 1 päivä). Päivitystunnuksia käytetään uusien pääsytunnusten hankkimiseen ilman, että käyttäjän tarvitsee kirjautua uudelleen sisään.
- `ROTATE_REFRESH_TOKENS`: Kierrätetäänkö päivitystunnuksia jokaisen käytön jälkeen.
- `BLACKLIST_AFTER_ROTATION`: Lisätäänkö vanhat päivitystunnukset mustalle listalle kierrätyksen jälkeen.
- `ALGORITHM`: Algoritmi, jota käytetään JWT:n allekirjoittamiseen (HS256 on yleinen valinta).
- `SIGNING_KEY`: Salainen avain, jota käytetään JWT:n allekirjoittamiseen (yleensä Django SECRET_KEY).
- `AUTH_HEADER_TYPES`: Valtuutusotsikon tyyppi (yleensä "Bearer").
- Sisällytä kirjautumisen ja päivitystunnuksen API-näkymät:
`djangorestframework-simplejwt` tarjoaa näkymät tunnusten hankkimiseen ja päivittämiseen. Sisällytä ne `urls.py`-tiedostoosi:
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` tarjoaa pääsy- ja päivitystunnukset onnistuneen todennuksen jälkeen. `TokenRefreshView` tarjoaa uuden pääsytunnuksen, kun sille annetaan kelvollinen päivitystunnus.
- Toteuta API-näkymäsi:
Tässä yksinkertainen esimerkki näkymästä, joka vaatii JWT-todennuksen:
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': 'Hei, ' + request.user.username + '! Olet todennettu.',
}
return Response(content)
Kuten tunnus-todennusesimerkissä, `authentication_classes` määrittää, että JWT-todennusta tulisi käyttää, ja `permission_classes` rajoittaa pääsyn vain todennetuille käyttäjille.
JWT-todennuksen edut
- Skaalautuvuus: Tunnuksen kelpoisuuden tarkistamiseen ei tarvita tietokantahakua, mikä tekee siitä skaalautuvamman.
- Tilaamaton: JWT sisältää kaikki tarvittavat tiedot todennusta varten.
- Standardisoitu: JWT on laajalti hyväksytty standardi, jota monet kirjastot ja alustat tukevat.
- Mikropalveluystävällinen: Soveltuu mikropalveluarkkitehtuureihin, koska palvelut voivat itsenäisesti varmentaa JWT:t.
JWT-todennuksen haitat
- Monimutkaisuus: Monimutkaisempi toteuttaa kuin tunnus-todennus.
- Tunnuksen koko: JWT:t voivat olla suurempia kuin yksinkertaiset tunnukset, mikä saattaa lisätä kaistanleveyden käyttöä.
- Tunnuksen peruuttaminen: JWT:n peruuttaminen on haastavaa. Kerran myönnettynä se on voimassa vanhenemiseensa asti. Kiertoteitä ovat peruutettujen tunnusten lisääminen mustalle listalle, mikä palauttaa tietokantariippuvuuden.
Tunnusten peruutusstrategiat
Sekä tunnus- että JWT-todennusmenetelmät vaativat mekanismeja pääsyn peruuttamiseen. Näin voit lähestyä tunnuksen peruuttamista:
Tunnus-todennuksen peruuttaminen
Tunnus-todennuksessa peruuttaminen on suoraviivaista: poista tunnus tietokannasta:
from rest_framework.authtoken.models import Token
try:
token = Token.objects.get(user=request.user)
token.delete()
except Token.DoesNotExist:
pass
JWT-todennuksen peruuttaminen
JWT:n peruuttaminen on monimutkaisempaa, koska tunnus itsessään on itsenäinen eikä se (aluksi) luota tietokantahakuun kelpoisuuden tarkistamiseksi. Yleisiä strategioita ovat:
- Tunnusten mustalle listalle asettaminen: Tallenna peruutettujen tunnusten tiedot mustalle listalle (esim. tietokantatauluun tai Redis-välimuistiin). Ennen JWT:n kelpoisuuden tarkistamista tarkista, onko se mustalla listalla. `djangorestframework-simplejwt` tarjoaa sisäänrakennetun tuen päivitystunnusten mustalle listalle asettamiselle.
- Lyhyet vanhenemisajat: Käytä lyhyitä pääsytunnusten vanhenemisaikoja ja luota päivitystunnuksiin uusien pääsytunnusten hankkimisessa usein. Tämä rajoittaa mahdollisuutta, että vaarantunutta tunnusta voitaisiin käyttää.
- Päivitystunnusten kierrätys: Kierrätä päivitystunnuksia jokaisen käytön jälkeen. Tämä mitätöi vanhat tunnukset joka kerta ja estää tunnusten varastamisen.
OAuth2 ja OpenID Connect
Monimutkaisemmissa todennus- ja valtuutusskenaarioissa harkitse OAuth2:n ja OpenID Connectin käyttöä. Nämä standardit tarjoavat vankan kehyksen pääsyn delegointiin resursseihin jakamatta tunnistetietoja. OAuth2 on ensisijaisesti valtuutusprotokolla, kun taas OpenID Connect rakentuu OAuth2:n päälle tarjotakseen todennuspalveluita. Useat Django-paketit, kuten `django-oauth-toolkit` ja `django-allauth`, helpottavat OAuth2:n ja OpenID Connectin integrointia DRF-API-rajapintoihisi.
Esimerkkiskenaario: Käyttäjä haluaa antaa kolmannen osapuolen sovellukselle pääsyn API-rajapintaasi tallennettuihin tietoihinsa. OAuth2:n avulla käyttäjä voi valtuuttaa sovelluksen jakamatta käyttäjätunnustaan ja salasanaansa. Sen sijaan sovellus saa pääsytunnuksen, jolla se voi käyttää käyttäjän tietoja määritellyn käyttöoikeuslaajuuden puitteissa.
Oikean todennusmenetelmän valinta
Paras todennusmenetelmä riippuu erityisvaatimuksistasi:
- Yksinkertaisuus ja toteutuksen nopeus: Tunnus-todennus on yleensä helpompi toteuttaa aluksi.
- Skaalautuvuus: JWT-todennus on skaalautuvampi korkean liikenteen API-rajapinnoille.
- Tietoturvavaatimukset: Harkitse tietojesi arkaluonteisuutta ja vaadittavaa tietoturvatasoa. OAuth2/OpenID Connect tarjoavat vankimmat tietoturvaominaisuudet, mutta vaativat monimutkaisempaa toteutusta.
- Mikropalveluarkkitehtuuri: JWT:t soveltuvat hyvin mikropalveluihin, koska jokainen palvelu voi itsenäisesti varmentaa tunnukset.
Parhaat käytännöt API-todennukselle
- Käytä HTTPS:ää: Käytä aina HTTPS:ää salataksesi asiakkaan ja palvelimen välisen viestinnän, suojaten tunnistetiedot salakuuntelulta.
- Tallenna salaisuudet turvallisesti: Älä koskaan tallenna salaisia avaimia tai salasanoja selväkielisenä. Käytä ympäristömuuttujia tai turvallisia konfiguraationhallintatyökaluja.
- Toteuta nopeusrajoitus (Rate Limiting): Suojaa API-rajapintaasi väärinkäytöltä toteuttamalla nopeusrajoitus rajoittamaan asiakkaan tekemien pyyntöjen määrää tietyn ajan kuluessa.
- Validoi syöte: Validoi kaikki syötetiedot perusteellisesti estääksesi injektiohyökkäykset.
- Valvo ja kirjaa: Valvo API-rajapintaasi epäilyttävän toiminnan varalta ja kirjaa todennustapahtumat auditointitarkoituksiin.
- Päivitä kirjastot säännöllisesti: Pidä Django-, DRF- ja todennuskirjastosi ajan tasalla hyötyäksesi tietoturvakorjauksista ja parannuksista.
- Toteuta CORS (Cross-Origin Resource Sharing): Määritä CORS oikein sallimaan vain luotettujen verkkotunnusten pääsy API-rajapintaasi verkkoselaimista.
Yhteenveto
Oikean todennusmenetelmän valinta on ratkaisevan tärkeää DRF-API-rajapintojesi turvaamiseksi. Tunnus-todennus tarjoaa yksinkertaisuutta, kun taas JWT-todennus tarjoaa skaalautuvuutta ja joustavuutta. Ymmärtämällä kunkin menetelmän edut ja haitat sekä API-tietoturvan parhaat käytännöt voit rakentaa vankkoja ja turvallisia API-rajapintoja, jotka suojaavat tietojasi ja käyttäjiäsi.
Muista ottaa huomioon erityistarpeesi ja valita ratkaisu, joka tasapainottaa parhaiten turvallisuuden, suorituskyvyn ja toteutuksen helppouden. Tutustu OAuth2:een ja OpenID Connectiin monimutkaisempia valtuutusskenaarioita varten.