Ce tutoriel présentera les jetons Web JSON (JWT) et expliquera comment implémenter l'authentification JWT dans Django..
JWT est une chaîne JSON codée qui est passée dans les en-têtes pour authentifier les demandes. Il est généralement obtenu en hachant les données JSON avec une clé secrète. Cela signifie que le serveur n'a pas besoin d'interroger la base de données à chaque fois pour récupérer l'utilisateur associé à un jeton donné..
Lorsqu'un utilisateur se connecte avec succès à l'aide de ses informations d'identification, un jeton Web JSON est obtenu et enregistré dans la mémoire de stockage locale. Chaque fois que l'utilisateur souhaite accéder à une URL protégée, le jeton est envoyé dans l'en-tête de la demande. Le serveur recherche alors un JWT valide dans l'en-tête Authorization et, s'il est trouvé, l'utilisateur sera autorisé à accéder..
Un en-tête de contenu typique ressemblera à ceci:
Autorisation: porteur eyJhbGciOiJIUzI1NiIsI
Ci-dessous un diagramme montrant ce processus:
L'authentification est le processus permettant d'identifier un utilisateur connecté, tandis que l'autorisation consiste à déterminer si un utilisateur donné a le droit d'accéder à une ressource Web..
Dans ce tutoriel, nous allons construire un système d'authentification d'utilisateur simple dans Django en utilisant JWT comme mécanisme d'authentification..
Commençons.
Créez un répertoire dans lequel vous conserverez votre projet ainsi qu'un environnement virtuel pour installer les dépendances du projet..
mkdir myprojects cd myprojects virtual venv
Activer l'environnement virtuel:
source venv / bin / activate
Créer un projet Django.
django-admin startproject django_auth
Installer DRF et django-rest-framework-jwt en utilisant pip.
pip installer djangorestframework pip installer djangorestframework-jwt pip installer django
Continuons et ajoutons DRF à la liste des applications installées dans le répertoire settings.py
fichier.
Pour utiliser JWT, nous devons configurer les autorisations de django-rest-framework pour accepter les jetons Web JSON..
dans le settings.py
fichier, ajoutez les configurations suivantes:
REST_FRAMEWORK = 'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework_jwt.authentication.JSONWebTokenAuthentication',),
Créer une nouvelle application appelée utilisateurs qui gérera l'authentification et la gestion des utilisateurs.
cd django-auth django-admin.py utilisateurs startapp
Ajouter l’application utilisateurs à la liste des applications installées dans le settings.py
fichier.
Nous allons utiliser la base de données PostgreSQL car elle est plus stable et robuste.
Créer le auth
base de données et attribuer un utilisateur.
Basculez sur le compte Postgres sur votre machine en tapant:
sudo su postgres
Accédez à l'invite Postgres et créez la base de données:
psql postgres = # CREATE DATABASE auth;
Créer un rôle:
postgres = # CREATE ROLE django_auth AVEC MOT DE PASSE DE CONNEXION 'asdfgh';
Accorder l'accès à la base de données à l'utilisateur:
postgres = # DONNEZ TOUS LES PRIVILEGES A LA BASE DE DONNEES auth TO django_auth;
Installez le paquet psycopg2, ce qui nous permettra d’utiliser la base de données que nous avons configurée:
pip installer psycopg2
Editez la base de données SQLite actuellement configurée et utilisez la base de données Postgres.
BASES DE DONNEES = 'défaut': 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'auth', 'USER': 'django_auth', 'PASSWORD': 'asdfgh', 'HOST' 'localhost', 'PORT': ",
Django est livré avec un système d'authentification intégré qui est très élaboré, mais nous avons parfois besoin de faire des ajustements, et donc de créer un système d'authentification d'utilisateur personnalisé. Notre modèle utilisateur héritera de la AbstractBaseUser
classe fournie par django.contrib.auth.models
.
Dans users / models.py, nous commençons par créer le modèle User pour stocker les détails de l'utilisateur..
# users / models.py from __future__ import unicode_literals de django.db modèles d'importation de django.utils importez le fuseau horaire de django.contrib.auth.models import (AbstractBaseUser, PermissionsMixin) class User (AbstractBaseUser, PermissionsMixin): "" Base abstraite classe implémentant un modèle utilisateur complet avec des autorisations conformes à l’administrateur. "" "email = models.EmailField (max_length = 40, unique = True) first_name = models.CharField (max_length = 30, blank = True) last_name = models.CharField ( max_length = 30, blank = True) is_active = models.BooleanField (default = True) is_staff = models.BooleanField (default = False) date_joined = models.DateTimeField (default = timezone.now) objects = UserManager () USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['prenom', 'prenom'] def save (self, * args, ** kwargs): super (utilisateur, auto) .save (* args, ** kwargs) renvoie self
CHAMPS OBLIGATOIRES
contient tous les champs obligatoires de votre modèle utilisateur, à l'exception du champ de nom d'utilisateur et du mot de passe, car ces champs seront toujours demandés.
UserManager
est la classe qui définit la Créer un utilisateur
et crée un utilisateur
méthodes. Cette classe devrait venir avant la AbstractBaseUser
classe que nous avons définie ci-dessus. Allons-y et définissons-le.
from django.contrib.auth.models import (AbstractBaseUser, PermissionsMixin, BaseUserManager), classe UserManager (BaseUserManager): def _create_user (auto, email, mot de passe, ** extra_fields): "" "Crée et enregistre un utilisateur avec le courrier électronique donné password. "" "sinon email: raise ValueError ('l'email donné doit être défini') essayez: avec transaction.atomic (): user = self.model (email = email, ** extra_fields) user.set_password (mot de passe) user.save (using = self._db) renvoie l'utilisateur sauf: raise def create_user (self, email, mot de passe = None, ** extra_fields): extra_fields.setdefault ('is_staff', False) extra_fields.setdefault ('is_superuser', False ) return self._create_user (email, mot de passe, ** extra_fields) def create_superuser (auto, email, mot de passe, ** extra_fields): extra_fields.setdefault ('is_staff', True) extra_fields.setdefault ('is_superuser', True) retourne self ._create_user (email, mot de passe = mot de passe, ** extra_fields)
Les migrations permettent de mettre à jour le schéma de votre base de données chaque fois que vos modèles changent, sans perte de données..
Créer une migration initiale pour notre modèle d'utilisateurs et synchroniser la base de données pour la première fois.
python manage.py effectuer des migrations utilisateurs python manage.py migrer
Créez un superutilisateur en lançant la commande suivante:
python manage.py crée un utilisateur supérieur
Créons un noeud final pour permettre l'enregistrement de nouveaux utilisateurs. Nous allons commencer par sérialiser les champs du modèle utilisateur. Les sérialiseurs permettent de modifier les données en un formulaire plus facile à comprendre, tel que JSON ou XML. La désérialisation fait l'inverse, c'est-à-dire convertir les données en un formulaire pouvant être enregistré dans la base de données..
Créez utilisateurs / serializers.py et ajoutez le code suivant.
# utilisateurs / serializers.py de rest_framework import sérialiseurs from.models import Classe utilisateur UserSerializer (serializers.ModelSerializer): date_joined = serializers.ReadOnlyField () classe Meta (objet): modèle = Champs utilisateur = ('id', 'email', 'first_name', 'last_name', 'date_joined', 'password') extra_kwargs = 'password': 'write_only': True
Ensuite, nous voulons créer une vue afin que le client ait une URL pour créer de nouveaux utilisateurs..
Dans users.views.py, ajoutez les éléments suivants:
# users / views.py, classe CreateUserAPIView (APIView): # Autorise tout utilisateur (authentifié ou non) à accéder à cette url permission_classes = (AllowAny,) def post (auto, requête): user = request.data serializer = UserSerializer (data = serializer.is_valid (raise_exception = True) serializer.save () return Response (serializer.data, status = status.HTTP_201_CREATED)
Nous fixons classes_autorisations
à (AllowAny,)
pour permettre à n'importe quel utilisateur (authentifié ou non) d'accéder à cette URL.
Créer un fichier utilisateurs / urls.py
et ajoutez l'URL pour correspondre à la vue que nous avons créée. Ajoutez également le code suivant.
# users / urls.py de django.conf.urls import url, les modèles de .views import CreateUserAPIView urlpatterns = [url (r '^ create / $', CreateUserAPIView.as_view ()),]
Nous devons également importer les URL de l’application des utilisateurs vers le répertoire principal. django_auth / urls.py
fichier. Alors allez-y et faites cela. Nous utilisons le comprendre
fonctionne ici, alors n'oubliez pas de l'importer.
# django_auth / urls.py de l'URL d'importation django.conf.urls, inclure de l'URL django.contrib import admin urlpatterns = [url (r '^ admin /', admin.site.urls), url (r '^ user /', include ('users.urls', namespace = "users")),]
Maintenant que nous avons fini de créer le noeud final, faisons un test et voyons si nous sommes sur la bonne voie. Nous allons utiliser Postman pour faire les tests. Si vous n'êtes pas familier avec Postman, c'est un outil qui présente une interface graphique conviviale pour la création de requêtes et la lecture de réponses..
Comme vous pouvez le voir ci-dessus, le noeud final fonctionne comme prévu..
Nous utiliserons le module Jango Python de Django-REST Framework que nous avons installé au début de ce tutoriel. Il ajoute la prise en charge de l'authentification JWT pour les applications Django Rest Framework.
Mais d’abord, définissons quelques paramètres de configuration pour nos jetons et comment ils sont générés dans le fichier settings.py.
# settings.py date et heure d'importation JWT_AUTH = 'JWT_VERIFY': True, 'JWT_VERIFY_EXPIRATION': True, 'JWT_EXPIRATION_DELTA': datetime.timedelta (secondes = 3000), 'JWT_AUTH_HEADER_PREFIX', 'Bear'
JWT_VERIFY
: Il déclenchera un jwt.DecodeError si le secret est faux.JWT_VERIFY_EXPIRATION
: Définit l'expiration sur True, ce qui signifie que les jetons expireront après un certain temps. Le temps par défaut est cinq minutes.JWT_AUTH_HEADER_PREFIX
: Préfixe de valeur d'en-tête d'autorisation à envoyer avec le jeton. Nous l'avons défini comme Porteur
, et le défaut est JWT
.Dans utilisateurs / views.py
, ajouter le code suivant.
@api_view (['POST']) @permission_classes ([AllowAny,]) def authenticate_user (request): essayer: email = request.data ['email'] password = request.data ['mot de passe'] user = User.objects .get (email = email, mot de passe = mot de passe) si utilisateur: essayez: payload = jwt_payload_handler (utilisateur) token = jwt.encode (charge, paramètres.SECRET_KEY) user_details = user_details ['name'] = "% s% s "% (user.name, user.last_name) user_details ['token'] = token user_logged_in.send (sender = user .__ class__, request = request, user = user) return Réponse (user_details, status = status.HTTP_200_OK) sauf une exception. as e: augmenter e sinon: res = 'erreur': 'ne peut pas s'authentifier avec les informations d'identification données ou le compte a été désactivé' retourner Réponse (res, status = status.HTTP_403_FORBIDDEN) sauf KeyError: res = 'error' : 'veuillez fournir un email et un mot de passe' return Response (res)
Dans le code ci-dessus, la vue de connexion utilise le nom d'utilisateur et le mot de passe en entrée, puis crée un jeton avec les informations utilisateur correspondant aux informations d'identification transmises en tant que données utiles et le renvoie au navigateur. D'autres informations sur l'utilisateur, telles que le nom, sont également renvoyées au navigateur avec le jeton. Ce jeton sera utilisé pour s'authentifier lors de futures demandes..
Les classes d'autorisation sont définies sur autoriser
puisque tout le monde peut accéder à ce noeud final.
Nous enregistrons également la dernière heure de connexion de l'utilisateur avec ce code.
user_logged_in.send (sender = user .__ class__, request = request, utilisateur = utilisateur)
Chaque fois que l'utilisateur souhaite effectuer une demande d'API, il doit envoyer le jeton dans les en-têtes d'authentification afin d'authentifier la demande..
Testons ce terminal avec Postman. Ouvrez Postman et utilisez la demande pour vous authentifier auprès de l’un des utilisateurs que vous avez créé précédemment. Si la tentative de connexion réussit, la réponse ressemblera à ceci:
Jusqu'à présent, les utilisateurs peuvent s'inscrire et s'authentifier. Cependant, ils ont également besoin d'un moyen de récupérer et de mettre à jour leurs informations. Implémentons ceci.
Dans utilisateurs.views.py
, ajouter le code suivant.
class UserRetrieveUpdateAPIView (RetrieveUpdateAPIView): # Autorise uniquement les utilisateurs authentifiés à accéder à cette URL permission_classes = (IsAuthenticated,) serializer_class = UserSerializer def get (auto, requête, * arguments, ** kwargs): # serializer pour gérer la transformation de notre objet 'User' quelque chose que # peut être JSONified et envoyé au client. serializer = self.serializer_class (request.user) return Response (serializer.data, status = status.HTTP_200_OK) def put (auto, requête, * arguments, ** kwargs): serializer_data = request.data.get ('utilisateur', ) serializer = UserSerializer (request.user, data = data_serializer, partial = True) serializer.is_valid (raise_exception = True) serializer.save () renvoie une réponse (serializer.data, status = status.HTTP_200_OK)
Nous définissons d’abord les classes d’autorisations et mettons à Est authentifié
puisqu'il s'agit d'une URL protégée et que seuls les utilisateurs authentifiés peuvent y accéder.
Nous définissons ensuite un obtenir
méthode pour récupérer les détails de l'utilisateur. Après avoir récupéré les détails de l'utilisateur, un utilisateur authentifié mettra à jour ses détails à sa guise..
Mettez à jour vos URL pour définir le noeud final comme suit.
utilisateurs / urls.py depuis .views importer CreateUserAPIView, UserRetrieveUpdateAPIView urlpatterns = [url (r '^ update / $', UserRetrieveUpdateAPIView.as_view ()),]
Pour que la demande aboutisse, les en-têtes doivent contenir le jeton JWT, comme indiqué ci-dessous..
Si vous essayez de demander une ressource sans l'en-tête d'authentification, vous obtiendrez l'erreur suivante.
Si un utilisateur reste au-delà du temps spécifié dans JWT_EXPIRATION_DELTA
sans faire de demande, le jeton expirera et ils devront demander un autre jeton. Ceci est également démontré ci-dessous.
Ce didacticiel a présenté les éléments nécessaires pour construire avec succès un système d’authentification d’arrière-plan solide avec des jetons Web JSON..