Wprowadzenie.
W poprzednim wpisie przedstawiłem, w jaki sposób możemy zrealizować uwierzytelnianie przy pomocy tokena. Omawiany Token był wówczas tworzony w momencie tworzenia nowego konta. Wyobraźmy sobie taki przypadek, że posiadamy już aplikację, mamy zarejestrowanych użytkowników i chcemy wprowadzić dodatkową funkcjonalność w postaci tokena uwierzytelniającego. W związku z takim przypadkiem we wpisie przedstawiłem, w jaki sposób generować token dla aktualnych użytkowników oraz w jaki sposób użytkownik może pobrać swój token, żeby na przykład wprowadzić go do innej aplikacji korzystającej z naszego API.
Spis treści serii
- Django REST API cz. 1– Tworzenie nowego projektu
- Django REST API cz. 2 – ListAPIView
- Django REST API cz. 3 – Wbudowana strona logowania
- Django REST API cz. 4 – Widoki generyczne
- Django REST API cz. 5 – ListCreateAPIView i konfiguracja dostępu
- Django REST API cz. 6 – Uszczegóławianie odpowiedzi
- Django REST API cz. 7 – Określenie z góry wartości danych
- Django REST API cz. 8 – RetrieveDestroyAPIView
- Django REST API cz. 9 – RetrieveUpdateAPIView
- Django REST API cz. 10 – Nadpisywanie zachowań metod przed/po operacji zapisu/usuwania
- Django REST API cz. 11 – Rejestracja nowego użytkownika poprzez API
- Django REST API cz. 12 – Uwierzytelnianie przy pomocy Tokena
- Django REST API cz. 13 – Generowanie tokena dla istniejących użytkowników ⇐
Zakres artykułu.
- Generowanie tokena dla istniejących użytkowników
Generowanie tokena dla istniejących użytkowników
W pierwszym kroku stwórzmy serializer dla modelu Token. Dodatkowo niech ten serializer będzie zawierał tylko jedno pole o nazwie key, ponieważ pole to zawiera tokeny użytkowników.
class TokenSerializer(serializers.ModelSerializer): class Meta: model = Token fields = ('key',)
Przejdźmy teraz do pliku views.py, gdzie zaimportujmy model Token oraz nowo stworzony serializer TokenSerializer.
from django.contrib.auth.models import User from django.db.models import query from django.shortcuts import render from rest_framework import generics, serializers import rest_framework from rest_framework import permissions from .models import Author, Book, Borrow from .serializers import AuthorSerializer, BookSerializer, BorrowSerializer, BorrowReturnBookSerializer, UserSerializer, TokenSerializer # new from rest_framework.permissions import IsAuthenticated, BasePermission, SAFE_METHODS, IsAdminUser, IsAuthenticatedOrReadOnly, AllowAny from rest_framework.exceptions import ValidationError from django.utils import timezone from rest_framework.authtoken.models import Token # new
W następnym kroku stwórzmy nową klasę widoku UserTokenList(), która będzie odpowiedzialna za zwracanie naszego tokena. W moim przypadku zastosowałem dziedziczenie po klasie generics.ListAPIView(), ponieważ wprowadzany adres nie zawiera numeru id z naszym tokenem. Użycie klasy ListAPIView() powoduje, że w odpowiedzi dostaniemy całą listę tokenów, dlatego w tym przypadku musimy napisać metodę get_queryset(), gdzie do modelu Token należy zastosować filtr po użytkowniku, który wysyła request. Drugą modyfikacją klasy, którą należy przeprowadzić jest nadpisanie metody get(). W tym przypadku musimy sprawdzić, czy nasz użytkownik znajduje się w bazie danych użytkowników, jeżeli użytkownik istnieje, wówczas sprawdzamy, czy dla naszego użytkonika w bazie danych jest wygenerowany token, jeżeli takiego tokenu nie ma, wówczas trzeba wykonać dodatkową czynność, czyli należy stworzyć token.
class UserTokenList(generics.ListAPIView): queryset = Token.objects.all() serializer_class = TokenSerializer permission_classes = [IsAuthenticated] def get_queryset(self): return Token.objects.filter(user=self.request.user) def get(self, request, *args, **kwargs): user = User.objects.filter(username=self.request.user) if user.exists(): token = Token.objects.filter(user=self.request.user) if token.exists(): return self.list(request, *args, **kwargs) else: token = Token.objects.create(user=self.request.user) return self.list(request, *args, **kwargs) else: raise ValidationError('You are not signup')
Na koniec stwórzmy ścieżkę łączącą url z klasą widoku.
from django.contrib import admin from django.urls import path, include from restapiapp import views urlpatterns = [ path('admin/', admin.site.urls), # API path('api/authors/', views.AuthorList.as_view()), path('api/books/', views.BookList.as_view()), path('api/borrows/', views.BorrowList.as_view()), path('api/borrows/<int:pk>/', views.BorrowRetrieveDestroy.as_view()), path('api/borrows/<int:pk>/return/', views.BorrowReturnBookUpdate.as_view()), path('api/borrows/<int:pk>/edit/', views.BorrowRetrieveUpdate.as_view()), path('api/user/create', views.UserCreate.as_view()), path('api/user/login', views.UserTokenList.as_view()), # new # DRF path('api-auth/', include('rest_framework.urls')), ]
W tej chwili możemy przeprowadzić testy. W moim przypadku jak możecie zobaczyć mam dwa tokeny dla użytkownika Antek oraz Tomek.
Zaloguje się na konto Antka i przejdę pod adres 127.0.0.1:8000/api/user/login. Wynik, jaki otrzymałem zamieszczam poniżej.
Teraz tę samą procedurę przeprowadzę dla konta Tomka. Jak możemy zobaczyć, w jednym, jak i drugim przypadku wartości tokenów się zgadzają.
Na koniec sprawdźmy, jak zachowa się aplikacja, gdy zaloguję się na konto admina.
W odpowiedzi dostałem wartość klucza, która nie znajdowała się w bazie danych.
Sprawdźmy zatem, czy wartość tego klucza została wpisana do bazy danych. W tym celu należy przejść do panelu admina.
Jak widzimy, token został dodany do bazy danych i od teraz może zostać użyty przez inne aplikacje w celu uwierzytelniania naszego użytkownika.
Spis treści serii
- Django REST API cz. 1– Tworzenie nowego projektu
- Django REST API cz. 2 – ListAPIView
- Django REST API cz. 3 – Wbudowana strona logowania
- Django REST API cz. 4 – Widoki generyczne
- Django REST API cz. 5 – ListCreateAPIView i konfiguracja dostępu
- Django REST API cz. 6 – Uszczegóławianie odpowiedzi
- Django REST API cz. 7 – Określenie z góry wartości danych
- Django REST API cz. 8 – RetrieveDestroyAPIView
- Django REST API cz. 9 – RetrieveUpdateAPIView
- Django REST API cz. 10 – Nadpisywanie zachowań metod przed/po operacji zapisu/usuwania
- Django REST API cz. 11 – Rejestracja nowego użytkownika poprzez API
- Django REST API cz. 12 – Uwierzytelnianie przy pomocy Tokena
- Django REST API cz. 13 – Generowanie tokena dla istniejących użytkowników ⇐