Faits saillants de Django : modèles d'utilisateurs et authentification (partie 1)

Publié: 2022-03-10
Résumé rapide ↬ L'une des principales raisons de développer un site dynamique est d'authentifier les utilisateurs et de restreindre le contenu. Django fournit un puissant modèle utilisateur prêt à l'emploi, et dans cet article, nous allons parcourir la meilleure façon de fournir des flux d'authentification utilisateur sécurisés et intuitifs.

Il existe deux types de sites Web : les statiques et les dynamiques. Django est un framework pour développer des sites Web dynamiques. Alors qu'un site Web statique est un site Web qui présente uniquement des informations, il n'y a aucune interaction (au-delà de simples demandes de page) qui est enregistrée sur un serveur. Dans un site Web statique, le serveur envoie HTML, CSS et JavaScript à un client et c'est tout. Plus de fonctionnalités nécessitent un site Web dynamique, où le serveur stocke des informations et répond à l'interaction de l'utilisateur au-delà du simple service de pages. L'une des principales raisons de développer un site dynamique est d'authentifier les utilisateurs et de restreindre le contenu.

L'écriture, le déploiement et l'administration d'un site Web statique sont d'environ un ordre de grandeur plus faciles, moins chers et plus sûrs qu'un site dynamique. Ainsi, vous ne devez créer un site Web dynamique que si les capacités supplémentaires du paradigme dynamique sont nécessaires pour votre projet. Django simplifie et rationalise le processus de création d'un site dynamique avec ses composants intégrés. En tant que l'un des principaux composants d'une application Web dynamique, l'objet "compte d'utilisateur", comme la roue, est tentant de se réinventer, mais la forme standard convient à la plupart des utilisations. Django fournit un puissant modèle utilisateur prêt à l'emploi, et dans cet article, nous allons parcourir la meilleure façon de fournir des flux d'authentification utilisateur sécurisés et intuitifs.

Autres pièces de la série :

  • Faits saillants de Django : la création de modèles permet d'économiser des lignes (partie 2)
  • Faits saillants de Django : modèles, administration et exploitation de la base de données relationnelle (partie 3)
  • Faits saillants de Django : se disputer les ressources statiques et les fichiers multimédias (partie 4)

Mise en place

Si vous souhaitez créer votre propre application Django pour expérimenter les concepts de cet article, vous pouvez créer un répertoire (et de préférence un environnement virtuel) puis exécuter les commandes suivantes :

 pip install django django-admin startproject PROJECTNAME cd PROJECTNAME python manage.py startapp APPNAME python manage.py migrate python manage.py runserver

Si vous recherchez une procédure pas à pas pour créer votre premier projet Django, le site Web de Django en fournit un excellent. Dans cet article, nous n'utilisons pas d'exemple de projet, mais les concepts abordés s'appliqueront à presque toutes les applications Django.

Plus après saut! Continuez à lire ci-dessous ↓

Modèle utilisateur standard

Fondamentalement, le concept de compte utilisateur existe pour deux raisons : le contrôle d'accès et l'état personnalisé de l'application. Le contrôle d'accès est l'idée que les ressources d'un système ne sont disponibles que pour certains utilisateurs. L'état personnalisé dépend fortement de l'objectif de l'application, mais peut inclure des paramètres, des données ou tout autre enregistrement spécifique à un utilisateur individuel. Le modèle Django stock User fournit des approches sensées pour les deux cas d'utilisation.

Initialement, il existe deux types d'utilisateurs dans une application Django : les comptes superutilisateurs et les utilisateurs réguliers. Les super-utilisateurs ont tous les attributs et privilèges des comptes réguliers, mais ont également accès au panneau d'administration de Django, une application puissante que nous explorerons en détail dans un prochain article. Essentiellement, les superutilisateurs peuvent créer, modifier ou supprimer toutes les données de l'application, y compris d'autres comptes d'utilisateurs.

Fondamentalement, le concept de compte utilisateur existe pour deux raisons : le contrôle d'accès et l'état personnalisé de l'application.

"

Pour créer un superutilisateur sur votre propre application Django, exécutez :

 python manage.py createsuperuser

L'autre avantage d'un compte utilisateur est le stockage de données personnalisées dans la base de données. Par défaut, Django ne nécessite qu'un nom d'utilisateur et un mot de passe, mais fournit des champs facultatifs permettant aux utilisateurs de saisir leur prénom, leur nom et leur adresse e-mail. Vous pouvez lire une référence de modèle complète sur le site Web de Django. Nous discuterons de l'extension de ce modèle ci-dessous.

Sécurité et fiabilité

Django inclut un middleware de gestion de mot de passe substantiel avec le modèle utilisateur. Les mots de passe utilisateur doivent comporter au moins 8 caractères, pas uniquement des chiffres, ne pas correspondre trop étroitement au nom d'utilisateur et ne pas figurer sur une liste des 20 000 mots de passe les plus courants. Les formulaires de stock Django valident ces exigences. Lorsqu'un mot de passe est envoyé au serveur, il est chiffré avant d'être stocké, par défaut en utilisant l'algorithme PBKDF2 avec un hachage SHA256. Dans l'ensemble, le système de mot de passe par défaut offre une sécurité robuste sans aucun effort de la part du développeur. À moins que vous n'ayez une expertise spécifique et une raison impérieuse de changer la façon dont les mots de passe sont gérés dans votre application, ne modifiez pas ce comportement.

Un autre élément intégré pratique est l'exigence que les noms d'utilisateur soient uniques. Si vous y réfléchissez, s'il y avait deux utilisateurs avec le nom d'utilisateur "djangofan1" et que le serveur recevait une demande de connexion pour ce nom d'utilisateur, il ne saurait pas quel utilisateur tentait d'accéder à l'application. Malheureusement pour eux, le deuxième utilisateur qui tentera de s'inscrire auprès de "djangofan1" devra choisir un nom différent, peut-être "djangofan2". Cette contrainte d'unicité est appliquée au niveau de la base de données mais est à nouveau vérifiée par les formulaires fournis par Django.

Enfin, une note sur la suppression d'utilisateurs. Bien que la suppression d'utilisateurs soit une possibilité, la plupart des applications complexes auront un certain nombre de ressources liées à chaque compte d'utilisateur. Si vous souhaitez supprimer efficacement un utilisateur sans supprimer ces objets attachés, définissez plutôt le champ is_active de l'utilisateur sur false. Ensuite, ces autres ressources restent associées au compte au lieu d'être elles-mêmes supprimées, et le compte utilisateur peut être réactivé à tout moment par un superutilisateur. Notez que cela ne libère pas le nom d'utilisateur, mais définir le compte comme inactif en conjonction avec le changement du nom d'utilisateur en une valeur aléatoire et unique pourrait produire le même effet. Enfin, si les politiques de votre site ou la législation locale applicable exigent que les comptes d'utilisateurs soient entièrement supprimables, l'approche is_active ne sera pas suffisante.

À moins que vous n'ayez une expertise spécifique et une raison impérieuse de changer la façon dont les mots de passe sont gérés dans votre application, ne modifiez pas ce comportement.

"

Utilisation standard

Lorsque vous souhaitez enregistrer un nouveau compte utilisateur, la vue pour ce faire ressemblera probablement à ce qui suit dans views.py :

 from django.shortcuts import render, redirect from django.contrib.auth import authenticate, login from django.contrib.auth.forms import UserCreationForm def signup(request): if request.user.is_authenticated: return redirect('/') if request.method == 'POST': form = UserCreationForm(request.POST) if form.is_valid(): form.save() username = form.cleaned_data.get('username') password = form.cleaned_data.get('password1') user = authenticate(username=username, password=password) login(request, user) return redirect('/') else: return render(request, 'signup.html', {'form': form}) else: form = UserCreationForm() return render(request, 'signup.html', {'form': form})

Décomposons cela :

  • Si l'utilisateur est déjà connecté, nous le redirigeons hors de la page d'inscription.
  • Si la méthode de requête est POST, cela signifie que le formulaire de création d'un utilisateur a déjà été rempli et qu'il est temps de créer un utilisateur.
    • Tout d'abord, construisez l'objet de formulaire sur le backend avec les données fournies par l'utilisateur.
    • Si le formulaire est valide, créez l'utilisateur et connectez-le, puis envoyez-le à la page principale.
    • Sinon, renvoyez-les sur la page de création d'utilisateur avec des informations sur les données non valides (par exemple, ils ont demandé un nom d'utilisateur déjà utilisé).
  • Sinon, l'utilisateur accède à la page pour la première fois et devrait rencontrer le formulaire de création d'un nouveau compte.

Examinons maintenant la connexion au compte :

 from django.shortcuts import render, redirect from django.contrib.auth import authenticate, login from django.contrib.auth.forms import AuthenticationForm def signin(request): if request.user.is_authenticated: return render(request, 'homepage.html') if request.method == 'POST': username = request.POST['username'] password = request.POST['password'] user = authenticate(request, username=username, password=password) if user is not None: login(request, user) return redirect('/') else: form = AuthenticationForm(request.POST) return render(request, 'signin.html', {'form': form}) else: form = AuthenticationForm() return render(request, 'signin.html', {'form': form})

Autre panne :

  • Si l'utilisateur est déjà connecté, nous le redirigeons hors de la page de connexion.
  • Si la méthode de requête est POST, cela signifie que le formulaire de connexion a été rempli et qu'il est temps d'authentifier l'utilisateur auprès d'un compte.
    • Tout d'abord, authentifiez l'utilisateur avec les données fournies par l'utilisateur
    • Si le nom d'utilisateur et le mot de passe correspondent à un compte, connectez l'utilisateur
    • Sinon, ramenez-les à la page de connexion avec leurs informations de formulaire pré-remplies
  • Sinon, l'utilisateur accède à la page pour la première fois et doit rencontrer le formulaire de connexion.

Enfin, vos utilisateurs peuvent éventuellement vouloir se déconnecter. Le code de base de cette requête est simple :

 from django.shortcuts import render, redirect from django.contrib.auth import logout def signout(request): logout(request) return redirect('/')

Une fois que l'utilisateur s'est connecté à son compte, et jusqu'à ce qu'il se déconnecte sur cet appareil, il a une "session". Pendant ce temps, les demandes ultérieures de leur navigateur pourront accéder aux pages de compte uniquement. Un utilisateur peut avoir plusieurs sessions actives en même temps. Par défaut, les sessions n'expirent pas.

Lorsqu'un utilisateur a une session active sur son appareil, il s'enregistrera en tant que True pour la vérification request.user.is_authenticated . Une autre façon de restreindre les pages aux utilisateurs connectés uniquement est le décorateur @login_required au-dessus d'une fonction. Il existe plusieurs autres façons d'atteindre le même objectif, détaillées ici.

Si ce niveau de configuration dépasse ce que vous souhaitez effectuer, il existe une approche encore plus prête à l'emploi de la gestion des utilisateurs. Ces vues d'authentification de stock fournissent des itinéraires, des vues et des formulaires standard pour la gestion des utilisateurs et peuvent être modifiées en les attribuant à des URL personnalisées, en transmettant des modèles personnalisés ou même en sous-classant les vues pour plus de contrôle.

Extension du modèle utilisateur

En règle générale, vous devez étendre le modèle utilisateur pour fournir des contrôles d'accès plus précis ou stocker davantage de données utilisateur par compte. Nous allons explorer plusieurs cas courants ci-dessous.

Suppression de champs du modèle utilisateur

Contrairement à l'en-tête de cette section, je ne recommande pas d'apporter des modifications directement au modèle utilisateur ou au schéma de base de données associé ! Le modèle utilisateur générique est établi par défaut dans votre base de données lors de la configuration d'un nouveau projet Django. Tant de choses sont liées au modèle utilisateur par défaut que sa modification pourrait avoir des effets inattendus dans votre application (surtout si vous utilisez des bibliothèques tierces), par conséquent, l'ajout ou la suppression de champs n'est pas recommandé et n'est pas facilité par le framework.

Par défaut, les deux seuls champs obligatoires pour un utilisateur sont le nom d'utilisateur et le mot de passe. Si vous ne souhaitez utiliser aucun des autres champs, ignorez simplement leur existence, car un utilisateur peut être créé sans prénom, nom ou adresse e-mail. Il existe une collection de champs par défaut comme last_login et date_joined qui peuvent également être ignorés si vous ne les voulez pas. Si vous aviez une contrainte technique réelle qui nécessitait de supprimer des champs optionnels du modèle utilisateur, vous le sauriez déjà et n'auriez pas besoin de cet article.

Une raison courante pour laquelle vous souhaitez supprimer un champ dans le modèle utilisateur est de supprimer le nom d'utilisateur au profit de l'e-mail en tant qu'identifiant unique. Dans ce cas, lors de la création de l'utilisateur à partir des données du formulaire ou de l'authentification d'une demande, entrez simplement l'adresse e-mail comme nom d'utilisateur en plus de son utilisation dans le champ e-mail. Le champ de nom d'utilisateur appliquera toujours la contrainte d'unicité lorsque les noms d'utilisateur sont formatés en tant qu'adresses e-mail. Les chaînes sont des chaînes, elles seront traitées de la même manière.

Tant de choses sont liées au modèle utilisateur par défaut que sa modification peut avoir des effets inattendus dans votre application, en particulier si vous utilisez des bibliothèques tierces.

"

Ajouter des champs avec un profil

De même, si vous souhaitez stocker des informations supplémentaires sur vos utilisateurs, vous ne devez pas tenter de modifier le modèle d'utilisateur par défaut. Même pour un seul champ, définissez votre propre objet avec une relation un à un avec les utilisateurs existants. Ce modèle supplémentaire est souvent appelé le Profile . Supposons que vous vouliez stocker un deuxième prénom et une date de naissance (ddb) pour chaque utilisateur. Le Profile serait défini comme suit dans models.py :

 from django.db import models from django.contrib.auth.models import User class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) middle_name = models.CharField(max_length=30, blank=True) dob = models.DateField(null=True, blank=True)

Contrôle d'accès personnalisé

Votre application peut avoir nécessité une distinction entre différents types d'utilisateurs pour accéder aux informations et aux fonctions. Django fournit un système permettant de créer un contrôle d'accès personnalisé et précis : les autorisations et les groupes.

Les autorisations sont des objets qui déterminent l'accès aux ressources. Un utilisateur peut avoir une ou plusieurs autorisations. Par exemple, ils peuvent avoir un accès en lecture à une table de produits et un accès en écriture à une table de clients. L'implémentation exacte de l'autorisation varie considérablement selon l'application, mais l'approche de Django rend intuitive la définition des autorisations pour les données et l'attribution de ces autorisations aux utilisateurs.

Les applications pour les entreprises et autres grandes organisations implémentent souvent un contrôle d'accès basé sur les rôles. Essentiellement, un utilisateur peut avoir différents rôles, chacun ayant certaines autorisations. L'outil de Django pour implémenter ce modèle est le Groupe. Un groupe peut avoir n'importe quel nombre d'autorisations, qui peuvent chacune être attribuées à n'importe quel nombre de groupes. Un utilisateur obtient alors des autorisations non pas directement mais par son appartenance à des groupes, ce qui facilite l'administration de l'application.

Présentation : Intégration d'un fournisseur de paiement

Le processus précis d'intégration d'un processeur de paiement varie considérablement selon l'application et le fournisseur. Cependant, je vais couvrir le processus en termes généraux.

L'un des principaux avantages de l'externalisation des paiements est que le fournisseur est responsable du stockage et de la validation de données hautement réglementées telles que les informations de carte de crédit. Le service partage ensuite un jeton d'utilisateur unique avec votre application ainsi que des données sur leur historique de paiement. Comme pour l'ajout du profil, vous pouvez créer un modèle associé à l' User principal et stocker les données dans ce modèle. Comme pour les mots de passe, il est important de suivre l'intégration donnée avec le fournisseur pour éviter de stocker des informations sensibles de manière incorrecte.

Présentation : Connexion sociale

L'autre domaine vaste et complexe que je souhaite aborder brièvement est la connexion sociale. De grandes plates-formes comme Facebook et Google, ainsi que des sites plus petits comme GitHub, fournissent des API pour utiliser leurs services afin d'authentifier les utilisateurs. Semblable à un fournisseur de paiement, cela crée un enregistrement dans votre base de données reliant un compte à un compte dans leur base de données.

Vous souhaiterez peut-être inclure l'authentification sociale dans votre site pour faciliter l'inscription des utilisateurs sans créer un nouvel ensemble d'informations d'identification de connexion. Si votre application cible uniquement les clients qui utilisent déjà un site spécifique qui offre une option d'authentification sociale, cela peut vous aider à attirer des utilisateurs de ce marché en abaissant la barrière à l'entrée. De plus, si votre application a l'intention d'accéder aux données de l'utilisateur à partir d'un service tiers, la liaison des comptes lors de l'authentification simplifie le processus d'octroi des autorisations.

Cependant, il y a des inconvénients à utiliser l'authentification sociale. Les changements d'API ou les pannes du fournisseur tiers peuvent interrompre la disponibilité ou les activités de développement de votre application. En général, les dépendances externes ajoutent de la complexité à l'application. Enfin, il convient de tenir compte des politiques de collecte et d'utilisation des données des tiers avec lesquels vous vous intégrez et de vous assurer qu'elles correspondent à vos attentes et à celles de vos utilisateurs.

Si vous décidez que l'authentification sociale convient à votre application, heureusement, il existe une bibliothèque pour cela. Python Social Auth for Django est un package permettant d'activer les fonctionnalités de l'écosystème d'authentification sociale de Python dans les projets Django.

Emballer

Aussi universel que soit le compte utilisateur, son utilisation généralisée peut conduire à résoudre inutilement les mêmes problèmes. J'espère que cet article vous a montré la gamme de fonctionnalités puissantes disponibles dans Django et vous a donné une compréhension des responsabilités de base d'une application lors de la création de comptes d'utilisateurs.

Django Highlights est une série présentant des concepts importants du développement Web dans Django. Chaque article est écrit comme un guide autonome sur une facette du développement de Django destiné à aider les développeurs et les concepteurs frontaux à mieux comprendre «l'autre moitié» de la base de code. Ces articles sont principalement construits pour vous aider à comprendre la théorie et les conventions, mais contiennent des exemples de code, qui sont écrits en Django 3.0. Plusieurs concepts que nous avons abordés dans cet article, notamment les modèles, les utilisateurs administrateurs, les modèles et les formulaires, seront explorés individuellement en détail dans les prochains articles de cette série.

Autres pièces de la série :

  • Faits saillants de Django : la création de modèles permet d'économiser des lignes (partie 2)
  • Faits saillants de Django : modèles, administration et exploitation de la base de données relationnelle (partie 3)
  • Faits saillants de Django : se disputer les ressources statiques et les fichiers multimédias (partie 4)