Utilisation du système d’authentification de Django

Ce document présente l’utilisation du système d’authentification de Django dans sa configuration par défaut. Cette configuration a évolué afin de pouvoir répondre aux besoins les plus courants des projets, elle est capable de gérer une large palette de tâches, et elle possède une implémentation soigneuse des mots de passe et des permissions. Pour les projets où les besoins en terme d’authentification divergent de la configuration par défaut, Django permet d”étendre et de personnaliser l’authentification de manière approfondie.

L’authentification de Django fournit à la fois l’authentification et l’autorisation, regroupés sous le terme général de système d’authentification, dans la mesure où ces fonctions sont assez étroitement liées.

Objets utilisateurs

Les objets User se trouvent au cœur du système d’authentification. Ils représentent typiquement les personnes qui interagissent avec votre site et sont utilisés pour activer des fonctionnalités comme la restriction d’accès, l’enregistrement de profils utilisateurs, l’association de contenus avec leur créateur, etc. Une seule classe d’utilisateurs existe dans le système d’authentification de Django ; cela signifie donc que les « super-utilisateurs » ('superusers') ou les membres des équipes d’administration du site ( 'staff') ne sont que des objets utilisateur normaux ayant certains attributs définis, et non pas une classe différente d’objet utilisateur.

Les attributs principaux de l’utilisateur par défaut sont :

Consultez la documentation complète de l'API pour une référence exhaustive ; la documentation ci-après est plus orientée sur les tâches.

Création d’utilisateurs

La manière la plus directe de créer des utilisateurs est d’utiliser la fonction utilitaire create_user():

>>> from django.contrib.auth.models import User
>>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')

# At this point, user is a User object that has already been saved
# to the database. You can continue to change its attributes
# if you want to change other fields.
>>> user.last_name = 'Lennon'
>>> user.save()

Si vous avez installé l’interface d’administration de Django, vous pouvez aussi créer des utilisateurs interactivement.

Création de superutilisateurs

Les superutilisateurs peuvent être créés à l’aide de la commande createsuperuser:

$ python manage.py createsuperuser --username=joe --email=joe@example.com

Vous devrez saisir un mot de passe. Après l’avoir fait, l’utilisateur sera immédiatement créé. Si vous omettez les options --username ou --email, vous devrez aussi renseigner ces valeurs.

Modification des mots de passe

Django ne stocke pas de mots de passe bruts (en clair) dans le modèle d’utilisateur, mais uniquement une empreinte hachée (voir la documentation sur la façon dont sont gérés les mots de passe pour des détails plus complets). C’est pourquoi il faut éviter de manipuler directement l’attribut password de l’utilisateur et qu’une fonction utilitaire est employée pour créer un utilisateur.

Pour changer le mot de passe d’un utilisateur, vous disposez de plusieurs options :

manage.py changepassword *nom d'utilisateur* offre une méthode permettant de changer le mot de passe d’un utilisateur dans une ligne de commande. Vous serez invité à changer le mot de passe de l’utilisateur indiqué en le saisissant deux fois. Si les deux saisies correspondent, le nouveau mot de passe sera immédiatement défini. Si vous n’indiquez pas de nom d’utilisateur, la commande essaie de changer le mot de passe de l’utilisateur dont le nom correspond à l’utilisateur système en cours.

Il est aussi possible de changer un mot de passe de façon programmatique, en utilisant set_password():

>>> from django.contrib.auth.models import User
>>> u = User.objects.get(username='john')
>>> u.set_password('new password')
>>> u.save()

Si l’interface d’administration de Django est installée, vous pouvez aussi changer les mots de passe des utilisateurs dans les pages d’administration du système d’authentification.

Django fournit également des vues et des formulaires permettant aux utilisateurs de changer leur propre mot de passe.

Le changement de mot de passe d’un utilisateur déconnecte toutes ses sessions. Voir Invalidation de session lors du changement de mot de passe pour plus de détails.

Authentification des utilisateurs

authenticate(request=None, **credentials)

Utilisez authenticate() pour vérifier un jeu de données d’authentification. Cette méthode accepte les données d’authentification sous forme de paramètres nommés, username et password pour la configuration par défaut, vérifie ces données avec chaque moteur d’authentification et renvoie un objet User si l’authentification est valide pour un des moteurs. Si aucun moteur n’accepte l’authentification ou si un moteur génère PermissionDenied, la méthode renvoie None. Par exemple :

from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
    # A backend authenticated the credentials
else:
    # No backend authenticated the credentials

request est un objet HttpRequest facultatif qui est transmis à la méthode authenticate() des moteurs d’authentification.

Note

Ceci est une manière d’authentifier un jeu de données d’authentification à un bas niveau ; par exemple, c’est ce qui est utilisé par RemoteUserMiddleware. Vous n’aurez probablement pas l’usage de cette méthode, sauf si vous écrivez votre propre système d’authentification. Si vous recherchez un moyen de connecter un utilisateur, utilisez plutôt la classe LoginView.

Permissions et autorisations

Django contient un système intégré de permissions. Il permet d’attribuer des permissions à des utilisateurs ou des groupes d’utilisateurs particuliers.

Ce système est utilisé par le site d’administration de Django, mais vous avez tout loisir de l’utiliser dans votre propre code.

Le site d’administration de Django utilise les permissions ainsi :

  • L’accès à l’affichage d’un objet est limité aux utilisateurs possédant la permission « view » ou « change » pour ce type d’objet.
  • L’accès au formulaire d’ajout et l’ajout d’objet sont limités aux utilisateurs possédant la permission « add » pour ce type d’objet.
  • L’accès à la liste des objets pour modification, au formulaire de modification et la modification d’un objet sont limités aux utilisateurs possédant la permission « change » pour ce type d’objet.
  • L’accès à la suppression d’un objet est limité aux utilisateurs possédant la permission « delete » pour ce type d’objet.

Les permissions peuvent non seulement être attribuées par type d’objet, mais aussi par instance d’objet spécifique. En utilisant les méthodes has_view_permission(), has_add_permission(), has_change_permission() et has_delete_permission() fournies par la classe ModelAdmin, il est possible de personnaliser les permissions pour différentes instances d’objets du même type.

Les objets User possèdent deux champs plusieurs-à-plusieurs : groups et user_permissions. Les objets User peuvent accéder à leurs objets liés de la même façon que pour tout autre modèle Django:

myuser.groups.set([group_list])
myuser.groups.add(group, group, ...)
myuser.groups.remove(group, group, ...)
myuser.groups.clear()
myuser.user_permissions.set([permission_list])
myuser.user_permissions.add(permission, permission, ...)
myuser.user_permissions.remove(permission, permission, ...)
myuser.user_permissions.clear()

Permissions par défaut

Quand l’application django.contrib.auth figure dans le réglage INSTALLED_APPS, elle s’assure que les quatre permissions par défaut (« add », « change », « delete » et « view ») soient créées pour chaque modèle Django défini dans toutes les applications installées.

Ces permissions seront créées lorsque vous lancez manage.py migrate; au premier lancement de migrate après l’ajout de django.contrib.auth à INSTALLED_APPS, les permissions par défaut seront créées pour tous les modèles précédemment installés de même que pour tout nouveau modèle installé à ce moment-là. Par la suite, chaque nouvelle exécution de manage.py migrate crée les permissions par défaut pour les nouveaux modèles (la fonction qui crée les permissions est connectée au signal post_migrate).

En supposant qu’une application ait l’attribut app_label foo et qu’un modèle soit nommé Bar, voici comment il faut tester les permissions de base :

  • ajout : user.has_perm('foo.add_bar')
  • modification : user.has_perm('foo.change_bar')
  • suppression : user.has_perm('foo.delete_bar')
  • affichage  : user.has_perm('foo.view_bar')

Le modèle Permission est rarement accédé directement.

Groupes

Les modèles django.contrib.auth.models.Group sont une manière générique de segmenter les utilisateurs afin de pouvoir leur attribuer des permissions ou de les désigner par un nom défini. Un utilisateur peut appartenir à autant de groupes que nécessaire.

Un utilisateur d’un groupe reçoit automatiquement les permissions attribuées à ce groupe. Par exemple, si le groupe Éditeurs du site possède la permission can_edit_home_page, tout utilisateur membre du groupe possédera cette permission.

Au-delà des permissions, les groupes sont un bon moyen de regrouper les utilisateurs sous un nom défini, afin de leur attribuer certaines fonctionnalités particulières. Par exemple, vous pourriez créer un groupe Utilisateurs spéciaux et écrire ensuite du code qui leur donne accès à une section réservée aux membres sur le site, ou leur envoyer des courriels s’adressant uniquement aux membres.

Création programmatique de permissions

Bien que des permissions personnalisées puissent être définies dans la classe Meta d’un modèle, il est aussi possible de créer directement des permissions. Par exemple, vous pouvez créer la permission can_publish d’un modèle BlogPost dans myapp:

from myapp.models import BlogPost
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

content_type = ContentType.objects.get_for_model(BlogPost)
permission = Permission.objects.create(
    codename='can_publish',
    name='Can Publish Posts',
    content_type=content_type,
)

La permission peut ensuite être attribuée à un User par son attribut user_permissions ou à un Group par son attribut permissions.

Les modèles mandataires ont besoin de leur propre type de contenu

Si vous souhaitez créer des permission pour un modèle mandataire, passez for_concrete_model=False à ContentTypeManager.get_for_model() pour obtenir le type ContentType approprié

content_type = ContentType.objects.get_for_model(BlogPostProxy, for_concrete_model=False)
Changed in Django 2.2:

Dans les anciennes versions, les modèles mandataires utilisent le type de contenu de leur modèle concret.

Mise en cache des permissions

Le moteur ModelBackend met en cache les permissions de l’objet utilisateur la première fois que ces permissions doivent être consultées. Cela convient généralement bien au cycle requête-réponse car en principe les permissions ne sont pas consultées immédiatement après avoir été ajoutées (dans l’interface d’administration par exemple). Si vous ajoutez des permissions et que vous les consultez immédiatement après, par exemple dans un test ou une vue, la solution la plus simple est de récupérer une nouvelle fois l’objet utilisateur à partir de la base de données. Par exemple :

from django.contrib.auth.models import Permission, User
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import get_object_or_404

from myapp.models import BlogPost

def user_gains_perms(request, user_id):
    user = get_object_or_404(User, pk=user_id)
    # any permission check will cache the current set of permissions
    user.has_perm('myapp.change_blogpost')

    content_type = ContentType.objects.get_for_model(BlogPost)
    permission = Permission.objects.get(
        codename='change_blogpost',
        content_type=content_type,
    )
    user.user_permissions.add(permission)

    # Checking the cached permission set
    user.has_perm('myapp.change_blogpost')  # False

    # Request new instance of User
    # Be aware that user.refresh_from_db() won't clear the cache.
    user = get_object_or_404(User, pk=user_id)

    # Permission cache is repopulated from the database
    user.has_perm('myapp.change_blogpost')  # True

    ...

Modèles mandataires

Les modèles mandataires fonctionnent exactement de la même manière que les modèles concrets. Les permissions sont créées en utilisant le type de contenu propre au modèle mandataire. Les modèles mandataires n’héritent pas des permissions du modèle concret qu’ils étendent

class Person(models.Model):
    class Meta:
        permissions = [('can_eat_pizzas', 'Can eat pizzas')]

class Student(Person):
    class Meta:
        proxy = True
        permissions = [('can_deliver_pizzas', 'Can deliver pizzas')]

>>> # Fetch the content type for the proxy model.
>>> content_type = ContentType.objects.get_for_model(Student, for_concrete_model=False)
>>> student_permissions = Permission.objects.filter(content_type=content_type)
>>> [p.codename for p in student_permissions]
['add_student', 'change_student', 'delete_student', 'view_student',
'can_deliver_pizzas']
>>> for permission in student_permissions:
...     user.user_permissions.add(permission)
>>> user.has_perm('app.add_person')
False
>>> user.has_perm('app.can_eat_pizzas')
False
>>> user.has_perms(('app.add_student', 'app.can_deliver_pizzas'))
True
Changed in Django 2.2:

Dans les anciennes versions, les permissions des modèles mandataires utilisent le type de contenu de leur modèle concret au lieu de celui du modèle mandataire.

Authentification dans les requêtes Web

Django utilise les sessions et le système de middleware pour brancher le système d’authentification dans les objets requête.

Un attribut request.user représentant l’utilisateur actuel est défini sur chaque objet requête. Si cet utilisateur ne s’est pas connecté, cet attribut sera constitué d’une instance de AnonymousUser, sinon il s’agira d’une instance de User.

Vous pouvez les différencier par la méthode is_authenticated, comme ceci :

if request.user.is_authenticated:
    # Do something for authenticated users.
    ...
else:
    # Do something for anonymous users.
    ...

Connexion d’un utilisateur

Si vous disposez d’un utilisateur authentifié que vous voulez faire correspondre à la session en cours, utilisez la fonction login().

login(request, user, backend=None)

Pour connecter un utilisateur à partir d’une vue, utilisez login(). Cette fonction accepte un objet HttpRequest et un objet User. login() enregistre l’identifiant de l’utilisateur dans la session en employant l’infrastructure des sessions de Django.

Notez que toute information définie durant la session anonyme d’un utilisateur est conservée dans la session à la suite du processus de connexion.

Cet exemple montre comment utiliser à la fois authenticate() et login():

from django.contrib.auth import authenticate, login

def my_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(request, username=username, password=password)
    if user is not None:
        login(request, user)
        # Redirect to a success page.
        ...
    else:
        # Return an 'invalid login' error message.
        ...

Choix du moteur d’authentification

Lorsqu’un utilisateur se connecte, son identifiant et le moteur utilisé pour son authentification sont enregistrés dans la session de l’utilisateur. Cela permet au même moteur d’authentification de récupérer les détails de l’utilisateur lors d’une prochaine requête. Le moteur d’authentification qui sera enregistré dans la session est choisi comme ceci :

  1. Si le paramètre backend factultatif est fourni, c’est celui-là qui est utilisé.
  2. Si un attribut user.backend existe, c’est celui-là qui est utilisé. Cela permet de combiner authenticate() et login(): authenticate() définit l’attribut user.backend sur l’objet utilisateur qu’il renvoie.
  3. S’il n’y a qu’un seul moteur dans AUTHENTICATION_BACKENDS, c’est celui-là qui est utilisé.
  4. Sinon, une exception est produite.

Dans les deux premiers cas, la valeur du paramètre backend ou l’attribut user.backend doit correspondre à une chaîne de chemin pointé (comme la syntaxe dans AUTHENTICATION_BACKENDS), et non pas la classe de moteur réelle.

Déconnexion d’un utilisateur

logout(request)

Pour déconnecter un utilisateur qui a été connecté par django.contrib.auth.login(), utilisez django.contrib.auth.logout() depuis la vue. Cette fonction accepte un objet HttpRequest et ne renvoie aucune valeur. Exemple :

from django.contrib.auth import logout

def logout_view(request):
    logout(request)
    # Redirect to a success page.

Notez que logout() ne signale pas d’erreur si l’utilisateur n’était pas connecté.

Lorsque vous appelez logout(), les données de session de la requête en cours sont complètement effacées. Ce comportement empêche une autre personne d’utiliser le même navigateur Web pour se connecter et obtenir accès aux données de session de l’utilisateur précédent. Si vous souhaitez placer des informations dans la session qui doivent être disponibles pour l’utilisateur immédiatement après une déconnexion, faites-le après avoir appelé django.contrib.auth.logout().

Restriction d’accès aux utilisateurs connectés

La manière brute

La manière directe de limiter l’accès à certaines pages est de vérifier request.user.is_authenticated et de rediriger l’utilisateur vers la page de connexion le cas échéant :

from django.conf import settings
from django.shortcuts import redirect

def my_view(request):
    if not request.user.is_authenticated:
        return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
    # ...

…ou d’afficher un message d’erreur :

from django.shortcuts import render

def my_view(request):
    if not request.user.is_authenticated:
        return render(request, 'myapp/login_error.html')
    # ...

Le décorateur login_required

login_required(redirect_field_name='next', login_url=None)

Comme raccourci, vous pouvez utiliser le décorateur login_required() bien pratique :

from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
    ...

login_required() effectue ceci :

  • Si l’utilisateur n’est pas connecté, il redirige vers settings.LOGIN_URL en transmettant le chemin absolu dans la chaîne de requête. Exemple : /accounts/login/?next=/polls/3/.
  • Si l’utilisateur est connecté, il exécute la vue normalement. Le code de la vue peut légitimement considérer l’utilisateur comme connecté.

Par défaut, le chemin vers lequel l’utilisateur doit être redirigé après un processus de connexion réussi est stocké dans le paramètre de chaîne de requête nommé "next". Si vous préférez que ce paramètre soit nommé différemment, login_required() accepte un paramètre facultatif redirect_field_name:

from django.contrib.auth.decorators import login_required

@login_required(redirect_field_name='my_redirect_field')
def my_view(request):
    ...

Notez que si vous indiquez une valeur pour redirect_field_name, il faudra très probablement aussi personnaliser le gabarit de connexion, dans la mesure où la variable de contexte du gabarit qui stocke le chemin de redirection utilise la valeur de redirect_field_name comme clé à la place de "next" (la valeur par défaut).

login_required() accepte également un paramètre facultatif login_url. Exemple :

from django.contrib.auth.decorators import login_required

@login_required(login_url='/accounts/login/')
def my_view(request):
    ...

Notez que si vous ne renseignez pas le paramètre login_url, vous devez vous assurer que le réglage settings.LOGIN_URL et votre vue de connexion sont correctement liés. Par exemple, en utilisant les paramètres par défaut, ajoutez les lignes suivantes dans votre configuration d’URL :

from django.contrib.auth import views as auth_views

path('accounts/login/', auth_views.LoginView.as_view()),

Le réglage settings.LOGIN_URL accepte également des noms de fonction vue et des motifs d’URL nommés. Cela permet de déplacer librement la vue de connexion dans la configuration d’URL sans avoir besoin de mettre à jour le réglage.

Note

Le décorateur login_required ne vérifie PAS le drapeau is_active d’un utilisateur, mais le moteur AUTHENTICATION_BACKENDS par défaut rejette les utilisateurs inactifs.

Voir aussi

Si vous écrivez des vues personnalisées pour le site d’administration de Django (ou que vous avez besoin des mêmes contrôles d’autorisation que les vues intégrées utilisent), le décorateur django.contrib.admin.views.decorators.staff_member_required() pourrait vous être encore plus utile que login_required().

La classe mixin LoginRequired

Lors de l’utilisation des vues fondées sur les classes, vous pouvez obtenir le même comportement qu’avec login_required en utilisant LoginRequiredMixin. Cette classe mixin doit se trouver à la position la plus à gauche de la chaîne d’héritage.

class LoginRequiredMixin

Si une vue utilise cette classe mixin, toutes les requêtes par des utilisateurs non authentifiés seront redirigées vers la page de connexion ou traitées comme des erreurs HTTP 403 Forbidden, selon le paramètre raise_exception.

Vous pouvez définir n’importe lequel des paramètres de AccessMixin pour personnaliser le traitement des utilisateurs non authentifiés :

from django.contrib.auth.mixins import LoginRequiredMixin

class MyView(LoginRequiredMixin, View):
    login_url = '/login/'
    redirect_field_name = 'redirect_to'

Note

Comme pour le décorateur login_required, cette classe mixin ne vérifie PAS le drapeau is_active d’un utilisateur, mais le moteur AUTHENTICATION_BACKENDS par défaut rejette les utilisateurs inactifs.

Restriction d’accès aux utilisateurs connectés passant un test

Pour limiter l’accès en fonction d’une certaine permission ou d’un test quelconque, le procédé est presque identique à celui décrit dans la section précédente.

Vous pouvez effectuer le test sur request.user directement dans la vue. Par exemple, cette vue vérifie que l’utilisateur possède bien une adresse électronique dans le domaine prévu et, dans le cas contraire, redirige vers la page de connexion :

from django.shortcuts import redirect

def my_view(request):
    if not request.user.email.endswith('@example.com'):
        return redirect('/login/?next=%s' % request.path)
    # ...
user_passes_test(test_func, login_url=None, redirect_field_name='next')

Comme raccourci, vous pouvez utiliser le décorateur user_passes_test qui procède à une redirection lorsque la fonction décorée renvoie False:

from django.contrib.auth.decorators import user_passes_test

def email_check(user):
    return user.email.endswith('@example.com')

@user_passes_test(email_check)
def my_view(request):
    ...

user_passes_test() requiert un paramètre : un exécutable acceptant un objet User et renvoyant True si l’utilisateur est autorisé à voir la page. Notez que user_passes_test() ne contrôle pas d’office que l’objet User n’est pas anonyme.

user_passes_test() accepte deux paramètres facultatifs :

login_url
Permet d’indiquer l’URL vers laquelle les utilisateurs ne passant pas le test seront redirigés. Cela peut être une page de connexion, la valeur par défaut étant settings.LOGIN_URL.
redirect_field_name
Comme pour login_required(). Si vous définissez ce paramètre à None, il ne sera pas présent dans l’URL, ce qui peut être intéressant si vous redirigez des utilisateurs qui ne passent pas le test vers une page ne servant pas à se connecter et où il n’y a pas de concept de « page suivante ».

Par exemple :

@user_passes_test(email_check, login_url='/login/')
def my_view(request):
    ...
class UserPassesTestMixin

Quand on utilise les vues fondées sur les classes, on peut utiliser la classe UserPassesTestMixin pour faire cela.

test_func()

Vous devez surcharger la méthode test_func() de la classe pour fournir le test qui sera effectué. De plus, vous pouvez définir n’importe lequel des paramètres de AccessMixin pour personnaliser le traitement des utilisateurs non authentifiés :

from django.contrib.auth.mixins import UserPassesTestMixin

class MyView(UserPassesTestMixin, View):

    def test_func(self):
        return self.request.user.email.endswith('@example.com')
get_test_func()

Vous pouvez aussi surcharger la méthode get_test_func() si vous souhaitez que la classe mixin utilise une autre méthode pour cette vérification (au lieu de test_func()).

Accumulation de UserPassesTestMixin

En raison de l’implémentation de UserPassesTestMixin, il n’est pas possible d’en combiner plusieurs dans la chaîne d’héritage. Le code suivant ne fonctionnera PAS :

class TestMixin1(UserPassesTestMixin):
    def test_func(self):
        return self.request.user.email.endswith('@example.com')

class TestMixin2(UserPassesTestMixin):
    def test_func(self):
        return self.request.user.username.startswith('django')

class MyView(TestMixin1, TestMixin2, View):
    ...

Si TestMixin1 appelait super() et prenait en compte le résultat, TestMixin1 ne fonctionnerait plus de façon autonome.

Le décorateur permission_required

permission_required(perm, login_url=None, raise_exception=False)

Il est relativement courant de devoir vérifier que l’utilisateur dispose d’une certaine permission. À cet effet, Django fournit un raccourci : le décorateur permission_required():

from django.contrib.auth.decorators import permission_required

@permission_required('polls.add_choice')
def my_view(request):
    ...

Comme pour la méthode has_perm(), les noms de permission ont la forme "<étiquette application>.<code permission>" (par ex. polls.add_choice pour une permission d’un modèle de l’application polls).

Le décorateur accepte aussi une liste de permissions, auquel cas l’utilisateur doit posséder toutes les permissions de la liste afin d’avoir accès à la vue.

Notez que permission_required() accepte également un paramètre facultatif login_url:

from django.contrib.auth.decorators import permission_required

@permission_required('polls.add_choice', login_url='/loginpage/')
def my_view(request):
    ...

Comme pour le décorateur login_required(), la valeur par défaut de login_url est settings.LOGIN_URL.

Si le paramètre raise_exception est présent, le décorateur génère une exception PermissionDenied (permission refusée), déclenchant la vue 403 (HTTP Forbidden) au lieu de rediriger vers la page de connexion.

Si vous souhaitez utiliser raise_exception tout en laissant aux utilisateurs une chance de se connecter, vous pouvez ajouter le décorateur login_required():

from django.contrib.auth.decorators import login_required, permission_required

@login_required
@permission_required('polls.add_choice', raise_exception=True)
def my_view(request):
    ...

Ceci évite aussi une boucle de redirection lorsque redirect_authenticated_user=True dans LoginView et que l’utilisateur connecté ne possède pas toutes les permissions requises.

La classe mixin PermissionRequiredMixin

Pour appliquer des contrôles de permission aux vues fondées sur les classes, vous pouvez utiliser la classe PermissionRequiredMixin:

class PermissionRequiredMixin

Cette classe mixin, tout comme le décorateur permission_required, contrôle si l’utilisateur accédant à une vue possède toutes les permissions indiquées. La permission (ou une itération de permissions) doit être indiquée dans le paramètre permission_required:

from django.contrib.auth.mixins import PermissionRequiredMixin

class MyView(PermissionRequiredMixin, View):
    permission_required = 'polls.add_choice'
    # Or multiple of permissions:
    permission_required = ('polls.view_choice', 'polls.change_choice')

Vous pouvez définir n’importe lequel des paramètres de AccessMixin pour personnaliser le traitement des utilisateurs non authentifiés.

Vous pouvez également surcharger ces méthodes :

get_permission_required()

Renvoie une itération de noms de permissions utilisés par la classe mixin. Il s’agit par défaut du contenu de l’attribut permission_required, converti en tuple si nécessaire.

has_permission()

Renvoie une valeur booléenne indiquant si l’utilisateur actuel a la permission d’exécuter la vue décorée. Par défaut, ceci renvoie le résultat de l’appel à has_perms() avec la liste des permissions renvoyées par get_permission_required().

Redirection des requêtes non autorisées dans les vues fondées sur les classes

Pour faciliter la gestion des restrictions d’accès dans les vues fondées sur les classes, la classe AccessMixin peut être utilisée pour configurer le comportement d’une vue lorsque son accès est refusé. Les utilisateurs authentifiés reçoivent une réponse HTTP 403 Forbidden. Les utilisateurs anonymes sont redirigés vers la page de connexion ou reçoivent une réponse HTTP 403, en fonction de l’attribut raise_exception.

class AccessMixin
login_url

Valeur de renvoi par défaut de get_login_url(). Contient None par défaut auquel cas get_login_url() se rabat sur le contenu de settings.LOGIN_URL.

permission_denied_message

Valeur de renvoi par défaut de get_permission_denied_message(). Contient une chaîne vide par défaut.

redirect_field_name

Valeur de renvoi par défaut de get_redirect_field_name(). Contient "next" par défaut.

raise_exception

Si cet attribut est défini à True, une exception PermissionDenied est produite lorsque les conditions ne sont pas remplies. Si la valeur est False (par défaut), les utilisateurs anonymes sont redirigés vers la page de connexion.

get_login_url()

Renvoie l’URL vers laquelle les utilisateurs ne passant pas le test seront redirigés. Renvoie login_url le cas échéant, sinon settings.LOGIN_URL.

get_permission_denied_message()

Lorsque raise_exception vaut True, cette méthode peut être utilisée pour contrôler le message d’erreur transmis au gestionnaire d’erreur pour y être affiché à destination de l’utilisateur. Par défaut, renvoie l’attribut permission_denied_message.

get_redirect_field_name()

Renvoie le nom du paramètre de requête qui contiendra l’URL vers laquelle l’utilisateur sera redirigé à la suite d’une connexion réussie. Si cette valeur est None, aucun paramètre de requête ne sera ajouté. Renvoie par défaut l’attribut redirect_field_name.

handle_no_permission()

En fonction de la valeur de raise_exception, cette méthode peut soit générer une exception PermissionDenied, soit rediriger l’utilisateur vers login_url, incluant potentiellement redirect_field_name si celui-ci est défini.

Invalidation de session lors du changement de mot de passe

Si votre AUTH_USER_MODEL hérite de AbstractBaseUser ou implémente sa propre méthode get_session_auth_hash(), les sessions authentifiées comprendront la valeur de hachage renvoyée par cette fonction. Dans le cas d’un AbstractBaseUser, il s’agit d’une empreinte HMAC du champ de mot de passe. Django vérifie que la valeur de hachage dans la session de chaque requête correspond à celle qui est calculée durant la requête. Cela permet à un utilisateur de se déconnecter de l’ensemble de ses sessions en changeant son mot de passe.

Les vues fournies par défaut avec Django pour le changement de mot de passe, PasswordChangeView et user_change_password du module django.contrib.auth, mettent à jour la session avec la valeur de hachage du nouveau mot de passe pour que l’utilisateur qui change son mot de passe ne soit pas déconnecté. Si vous avez une vue personnalisée pour le changement de mot de passe et que vous souhaitez avoir un comportement similaire, utilisez la fonction update_session_auth_hash().

update_session_auth_hash(request, user)

Cette fonction accepte en entrée la requête actuelle ainsi que l’objet utilisateur mis à jour et à partir duquel la nouvelle valeur de hachage de la session sera calculée ; elle met à jour la valeur de hachage de la session. Elle se charge aussi d’alterner la clé de session afin qu’un cookie de session volé soit invalidé :

Exemple d’utilisation :

from django.contrib.auth import update_session_auth_hash

def password_change(request):
    if request.method == 'POST':
        form = PasswordChangeForm(user=request.user, data=request.POST)
        if form.is_valid():
            form.save()
            update_session_auth_hash(request, form.user)
    else:
        ...

Note

Comme get_session_auth_hash() se base sur SECRET_KEY, la mise à jour de la clé secrète sur votre site invalide toutes les sessions existantes.

Vues d’authentification

Django fournit plusieurs vues permettant de gérer la connexion, la déconnexion et le traitement des mots de passe. Elles font appel aux formulaires d’authentification intégrés, mais vous pouvez leur transmettre aussi vos propres formulaires.

Django fournit pas de gabarit par défaut pour les vues d’authentification. Vous devez créer vos propres gabarits pour les vues que vous souhaitez utiliser. Le contexte de gabarit est documenté dans chaque vue, voir Toutes les vues d’authentification.

Utilisation des vues

Il existe différentes méthodes pour mettre en œuvre ces vues dans votre projet. Le plus simple est d’inclure l’URLconf de django.contrib.auth.urls dans votre propre URLconf, par exemple

urlpatterns = [
    path('accounts/', include('django.contrib.auth.urls')),
]

Cela comprendra les modèles d’URL suivants

accounts/login/ [name='login']
accounts/logout/ [name='logout']
accounts/password_change/ [name='password_change']
accounts/password_change/done/ [name='password_change_done']
accounts/password_reset/ [name='password_reset']
accounts/password_reset/done/ [name='password_reset_done']
accounts/reset/<uidb64>/<token>/ [name='password_reset_confirm']
accounts/reset/done/ [name='password_reset_complete']

Les vues possèdent un nom d’URL pour les référencer plus facilement. Voir la documentation des URL pour plus de détails sur l’utilisation de modèles d’URL nommés.

Si vous voulez plus de contrôle sur vos URL, vous pouvez référencer une vue spécifique dans votre URLconf

from django.contrib.auth import views as auth_views

urlpatterns = [
    path('change-password/', auth_views.PasswordChangeView.as_view()),
]

Les vues ont des paramètres optionnels que vous pouvez utiliser pour modifier le comportement de la vue. Par exemple, si vous voulez changer le nom du modèle utilisé par une vue, vous pouvez fournir le paramètre template_name. Une façon de le faire est de fournir des paramètres mot-clé dans l’URLconf, ceux-ci seront transmis à la vue. Par exemple

urlpatterns = [
    path(
        'change-password/',
        auth_views.PasswordChangeView.as_view(template_name='change-password.html'),
    ),
]

Toutes les vues sont basées sur des classes ce qui permet de les personnaliser facilement par héritage.

Toutes les vues d’authentification

Ceci est une liste de toutes les vues fournies par django.contrib.auth. Pour les détails de l’implémentation, voir Utilisation des vues.

class LoginView

Nom d’URL : login

Consultez la documentation sur les URL pour plus de détails sur l’utilisation des motifs d’URL nommés.

Attributs :

  • template_name: le nom d’un gabarit pour afficher le résultat de la vue de connexion d’un utilisateur. Sa valeur par défaut est registration/login.html.

  • redirect_field_name: le nom d’un champ GET contenant l’URL vers laquelle rediriger après la connexion. Sa valeur par défaut est next.

  • authentication_form: un exécutable (typiquement une classe de formulaire) à utiliser pour l’authentification. Sa valeur par défaut est AuthenticationForm.

  • extra_context: un dictionnaire de données de contexte qui sera fusionné avec les données de contexte par défaut transmises au gabarit.

  • redirect_authenticated_user: une valeur booléenne indiquant si les utilisateurs authentifiés accédant à la page de connexion sont redirigés comme s’ils venaient de se connecter. La valeur par défaut est False.

    Avertissement

    Si vous activez redirect_authenticated_user, d’autres sites Web seront capables de déterminer si leurs visiteurs sont authentifiés sur votre site en faisant des requêtes de redirection vers des fichiers images de votre site. Pour éviter cette divulgation d’information par « empreinte de médias sociaux », servez toutes les images ainsi que la favicon depuis un domaine distinct.

    L’activation de redirect_authenticated_user peut aussi aboutir à une boucle de redirection lorsque le décorateur permission_required() est utilisé sans que le paramètre raise_exception ne soit indiqué.

  • success_url_allowed_hosts: un ensemble set d’hôtes, en plus de request.get_host(), qui sont sûrs comme cible de redirection après la connexion. L’ensemble set est vide par défaut.

Voici ce que fait LoginView:

  • Quand elle est appelée par GET, elle affiche un formulaire de connexion dont la cible POST envoie vers la même URL. Plus d’infos à ce sujet dans un moment.
  • Quand elle est appelée par POST avec les données d’authentification d’un utilisateur, elle tente de connecter cet utilisateur. Si l’opération réussit, la vue redirige vers l’URL indiquée dans next. Si next est absent, elle redirige vers settings.LOGIN_REDIRECT_URL (/accounts/profile/ par défaut). Si la connexion échoue, la vue affiche à nouveau le formulaire de connexion.

Il est de votre devoir de fournir le code HTML du gabarit de connexion, nommé registration/login.html par défaut. Ce gabarit reçoit quatre variables de contexte de gabarit :

  • form: un objet Form représentant le formulaire AuthenticationForm.
  • next: l’URL vers laquelle rediriger après une connexion réussie. Elle peut aussi contenir une chaîne de requête.
  • site: le Site actuel, selon le réglage SITE_ID. Si l’application site n’est pas installée, il s’agira d’une instance de RequestSite qui détecte le nom du site et son domaine à partir de l’objet HttpRequest en cours.
  • site_name: un alias de site.name. Si l’application site n’est pas installée, cette variable contiendra la valeur de request.META['SERVER_NAME']. Pour plus d’informations sur les sites, voir L’infrastructure des « sites ».

Si vous préférez ne pas utiliser le gabarit registration/login.html, vous pouvez renseigner le paramètre template_name via les paramètres supplémentaires de la méthode as_view dans votre configuration d’URL. Par exemple, cette ligne de configuration d’URL force l’utilisation de myapp/login.html:

path('accounts/login/', auth_views.LoginView.as_view(template_name='myapp/login.html')),

Vous pouvez également définir le nom du champ GET contenant l’URL vers laquelle rediriger après la connexion en utiliisant redirect_field_name. Par défaut, ce champ s’appelle next.

Voici un exemple de gabarit registration/login.html comme point de départ. Il compte sur la présence d’un gabarit base.html qui définit un bloc content:

{% extends "base.html" %}

{% block content %}

{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}

{% if next %}
    {% if user.is_authenticated %}
    <p>Your account doesn't have access to this page. To proceed,
    please login with an account that has access.</p>
    {% else %}
    <p>Please login to see this page.</p>
    {% endif %}
{% endif %}

<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table>
<tr>
    <td>{{ form.username.label_tag }}</td>
    <td>{{ form.username }}</td>
</tr>
<tr>
    <td>{{ form.password.label_tag }}</td>
    <td>{{ form.password }}</td>
</tr>
</table>

<input type="submit" value="login">
<input type="hidden" name="next" value="{{ next }}">
</form>

{# Assumes you setup the password_reset view in your URLconf #}
<p><a href="{% url 'password_reset' %}">Lost password?</a></p>

{% endblock %}

Si vous avez personnalisé l’authentification (voir Personnalisation de l’authentification), il est possible d’utiliser un formulaire d’authentification personnalisé en définissant l’attribut authentication_form. La méthode __init__() de ce formulaire doit accepter un paramètre nommé request; le formulaire doit également implémenter une méthode get_user() qui renvoie l’objet utilisateur authentifié (cette méthode n’est appelée qu’à la suite d’une validation de formulaire réussie).

class LogoutView

Déconnecte un utilisateur.

Nom d’URL : logout

Attributs :

  • next_page: l’URL vers laquelle rediriger après la déconnexion. La valeur par défaut est settings.LOGOUT_REDIRECT_URL.
  • template_name: le nom complet d’un gabarit à afficher après la déconnexion d’un utilisateur. Sa valeur par défaut est registration/logged_out.html.
  • redirect_field_name: le nom d’un champ GET contenant l’URL vers laquelle rediriger après la déconnexion. Sa valeur par défaut est next. Cela surcharge l’URL next_page si le paramètre GET indiqué est renseigné.
  • extra_context: un dictionnaire de données de contexte qui sera fusionné avec les données de contexte par défaut transmises au gabarit.
  • success_url_allowed_hosts: un ensemble set d’hôtes, en plus de request.get_host(), qui sont sûrs comme cible de redirection après la déconnexion. L’ensemble est vide par défaut.

Contexte de gabarit :

  • title: la chaîne « Logged out », traduite.
  • site: le Site actuel, selon le réglage SITE_ID. Si l’application site n’est pas installée, il s’agira d’une instance de RequestSite qui détecte le nom du site et son domaine à partir de l’objet HttpRequest en cours.
  • site_name: un alias de site.name. Si l’application site n’est pas installée, cette variable contiendra la valeur de request.META['SERVER_NAME']. Pour plus d’informations sur les sites, voir L’infrastructure des « sites ».
logout_then_login(request, login_url=None)

Déconnecte un utilisateur, puis redirige vers la page de connexion.

Nom d’URL : aucune URL par défaut

Paramètres facultatifs :

  • login_url: l’URL de la page de connexion vers laquelle rediriger. Si ce paramètre n’est pas renseigné, la valeur par défaut utilisée est settings.LOGIN_URL.
class PasswordChangeView

Nom d’URL : password_change

Permet à un utilisateur de changer son mot de passe.

Attributs :

  • template_name: le nom complet d’un gabarit à utiliser pour l’affichage du formulaire de changement de mot de passe. Sa valeur par défaut est registration/password_change_form.html si le paramètre n’est pas renseigné.
  • success_url: l’URL vers laquelle rediriger après un changement de mot de passe réussi. Contient 'password_change_done' par défaut.
  • form_class: un formulaire de changement de mot de passe personnalisé qui doit accepter un paramètre nommé user. Le formulaire est responsable de changer réellement le mot de passe de l’utilisateur. La valeur par défaut est PasswordChangeForm.
  • extra_context: un dictionnaire de données de contexte qui sera fusionné avec les données de contexte par défaut transmises au gabarit.

Contexte de gabarit :

  • form: le formulaire de changement de mot de passe (voir form_class ci-dessus).
class PasswordChangeDoneView

Nom d’URL : password_change_done

La page affichée après qu’un utilisateur a changé son mot de passe.

Attributs :

  • template_name: le nom complet d’un gabarit à utiliser. Sa valeur par défaut est registration/password_change_done.html si le paramètre n’est pas renseigné.
  • extra_context: un dictionnaire de données de contexte qui sera fusionné avec les données de contexte par défaut transmises au gabarit.
class PasswordResetView

Nom d’URL : password_reset

Permet à un utilisateur de réinitialiser son mot de passe en générant un lien à usage unique permettant la réinitialisation du mot de passe. Ce lien est envoyé à l’adresse électronique enregistrée pour cet utilisateur.

Si l’adresse électronique indiquée n’existe pas dans le système, cette vue n’envoie pas de courriel, mais l’utilisateur ne reçoit pas non plus de message d’erreur, ceci pour empêcher une divulgation d’information à de potentiels attaquants. Si vous souhaitez fournir un message d’erreur dans cette situation, vous pouvez créer une classe héritant de PasswordResetForm et employer l’attribut form_class.

Note

Soyez conscients que l’envoi d’un courriel prend un peu de temps, ce qui peut vous rendre vulnérable à une attaque temporelle d’énumération d’adresses électroniques en raison de la différence entre la durée d’une requête de réinitialisation quand l’adresse de courriel existe ou quand elle n’existe pas. Pour éviter cet écart temporel, vous pouvez utiliser un module tiers qui autorise l’envoi asynchrone de courriels, comme par exemple django-mailer.

Les utilisateurs possédant un mot de passe inutilisable (voir set_unusable_password()) ne sont pas autorisés à demander la réinitialisation de leur mot de passe afin de prévenir une utilisation abusive avec des sources d’authentification externes comme LDAP. Notez qu’ils ne reçoivent pas de message d’erreur car cela indiquerait que leur compte existe bel et bien, mais ils ne reçoivent pas de courriel non plus.

Attributs :

  • template_name: le nom complet d’un gabarit à utiliser pour l’affichage du formulaire de réinitialisation du mot de passe. Sa valeur par défaut est registration/password_reset_form.html si le paramètre n’est pas renseigné.
  • form_class: formulaire utilisé pour obtenir l’adresse électronique de l’utilisateur pour lequel le mot de passe doit être réinitialisé. La valeur par défaut est PasswordResetForm.
  • email_template_name: le nom complet d’un gabarit à utiliser pour produire le courriel contenant le lien de réinitialisation du mot de passe. Sa valeur par défaut est registration/password_reset_email.html si le paramètre n’est pas renseigné.
  • subject_template_name: le nom complet d’un gabarit à utiliser pour le sujet du courriel contenant le lien de réinitialisation du mot de passe. Sa valeur par défaut est registration/password_reset_subject.txt si le paramètre n’est pas renseigné.
  • token_generator: instance de la classe qui vérifie le lien à usage unique. La valeur par défaut est default_token_generator qui est une instance de django.contrib.auth.tokens.PasswordResetTokenGenerator.
  • success_url: l’URL vers laquelle rediriger après une demande de réinitialisation de mot de passe réussie. Contient 'password_reet_done' par défaut.
  • from_email: une adresse électronique valide. Par défaut, Django utilise DEFAULT_FROM_EMAIL.
  • extra_context: un dictionnaire de données de contexte qui sera fusionné avec les données de contexte par défaut transmises au gabarit.
  • html_email_template_name: le nom complet d’un gabarit à utiliser pour produire un courriel avec plusieurs parties text/html et contenant le lien de réinitialisation du mot de passe. Par défaut, le courriel n’est pas envoyé au format HTML.
  • extra_email_context: un dictionnaire de données de contexte qui sera disponible dans le gabarit du courriel. Il peut être utilisé pour surcharger les valeurs de contexte de gabarit par défaut énumérées ci-dessous, par ex. domain.

Contexte de gabarit :

  • form: le formulaire de réinitialisation du mot de passe de l’utilisateur (voir form_class ci-dessus).

Contexte de gabarit du courriel :

  • email: un alias de user.email
  • user: l’utilisateur User actuel, en accord avec le champ de formulaire email. Seuls les utilisateurs actifs ont la possibilité de réinitialiser leur mot de passe (User.is_active is True).
  • site_name: un alias de site.name. Si l’application site n’est pas installée, cette variable contiendra la valeur de request.META['SERVER_NAME']. Pour plus d’informations sur les sites, voir L’infrastructure des « sites ».
  • domain: un alias de site.domain. Si l’application site n’est pas installée, cette variable contiendra la valeur de request.get_host().
  • protocol: http ou https
  • uid: la clé primaire de l’utilisateur codée en base64.
  • token: jeton servant à contrôler la validité du lien de réinitialisation.

Exemple de registration/password_reset_email.html (gabarit de corps de message) :

Someone asked for password reset for email {{ email }}. Follow the link below:
{{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}

Le gabarit du sujet reçoit le même contexte de gabarit. Le sujet doit être une seule ligne de texte brut.

class PasswordResetDoneView

Nom d’URL : password_reset_done

La page affichée après qu’un utilisateur a reçu le lien pour réinitialiser son mot de passe. Cette vue est appelée par défaut si la vue PasswordResetView ne possède pas une URL success_url définie explicitement.

Note

Si l’adresse électronique fournie n’existe pas dans le système, si l’utilisateur est inactif ou si son mot de passe est inutilisable, cette vue sera tout de même affichée, mais aucun message ne sera envoyé.

Attributs :

  • template_name: le nom complet d’un gabarit à utiliser. Sa valeur par défaut est registration/password_reset_done.html si le paramètre n’est pas renseigné.
  • extra_context: un dictionnaire de données de contexte qui sera fusionné avec les données de contexte par défaut transmises au gabarit.
class PasswordResetConfirmView

Nom d’URL : password_reset_confirm

Affiche un formulaire pour saisir un nouveau mot de passe.

Paramètres nommés provenant de l’URL :

  • uidb64: l’identifiant de l’utilisateur codé en base 64.
  • token: jeton servant à contrôler la validité du mot de passe.

Attributs :

  • template_name: le nom complet d’un gabarit à utiliser pour l’affichage de la vue de confirmation du mot de passe. Sa valeur par défaut est registration/password_reset_confirm.html.

  • token_generator: instance de la classe qui vérifie le mot de passe. La valeur par défaut est default_token_generator qui est une instance de django.contrib.auth.tokens.PasswordResetTokenGenerator.

  • post_reset_login: une valeur booléenne indiquant si l’utilisateur doit être automatiquement authentifié à la suite d’une réinitialisation de mot de passe réussie. Vaut False par défaut.

  • post_reset_login_backend: un chemin Python vers le moteur d’authentification à utiliser lors d’une authentification si post_reset_login vaut True. Obligatoire seulement si plusieurs moteurs sont configurés dans AUTHENTICATION_BACKENDS. La valeur par défaut est None.

  • form_class: formulaire utilisé pour définir le mot de passe. La valeur par défaut est SetPasswordForm.

  • success_url: l’URL vers laquelle rediriger après une réinitialisation de mot de passe. Contient 'password_reset_complete' par défaut.

  • extra_context: un dictionnaire de données de contexte qui sera fusionné avec les données de contexte par défaut transmises au gabarit.

  • reset_url_token: paramètre jeton affiché comme composant des URL de réinitialisation de mot de passe. Contient 'set-password' par défaut.

    Changed in Django 3.0:

    L’attribut de classe reset_url_token a été ajouté.

Contexte de gabarit :

  • form: le formulaire de définition du mot de passe du nouvel utilisateur (voir form_class ci-dessus).
  • validlink: valeur booléenne, True si le lien (combinaison de uidb64 et de token) est valable ou pas encore utilisé.
class PasswordResetCompleteView

Nom d’URL : password_reset_complete

Affiche une vue informant l’utilisateur que son mot de passe a été changé avec succès.

Attributs :

  • template_name: le nom complet d’un gabarit pour afficher la vue. Sa valeur par défaut est registration/password_reset_complete.html.
  • extra_context: un dictionnaire de données de contexte qui sera fusionné avec les données de contexte par défaut transmises au gabarit.

Fonctions utilitaires

redirect_to_login(next, login_url=None, redirect_field_name='next')

Redirige vers la page de connexion, puis vers une autre URL si la connexion réussit.

Paramètres obligatoires :

  • next_page: l’URL vers laquelle rediriger après une connexion réussie.

Paramètres facultatifs :

  • login_url: l’URL de la page de connexion vers laquelle rediriger. Si ce paramètre n’est pas renseigné, la valeur par défaut utilisée est settings.LOGIN_URL.
  • redirect_field_name: le nom d’un champ GET contenant l’URL vers laquelle rediriger après la déconnexion. Cela surcharge next si le paramètre GET indiqué est renseigné.

Formulaires intégrés

Si vous ne souhaitez pas utiliser les vues intégrées mais que vous voulez profiter de ne pas devoir réécrire les formulaires de cette fonctionnalité, le système d’authentification fournit plusieurs formulaires intégrés se trouvant dans django.contrib.auth.forms:

Note

Les formulaires d’authentification intégrés comptent sur un certain nombre de caractéristiques du modèle utilisateur avec lequel ils interagissent. Si vous utilisez un modèle d’utilisateur personnalisé, il peut être nécessaire de définir vos propres formulaires pour le système d’authentification. Pour plus d’informations, consultez la documentation sur l”utilisation des formulaires d’authentification intégrés avec les modèles d’utilisateur personnalisés.

class AdminPasswordChangeForm

Un formulaire utilisé dans l’interface d’administration pour changer le mot de passe d’un utilisateur.

Accepte user comme premier paramètre positionnel.

class AuthenticationForm

Un formulaire pour connecter un utilisateur.

Accepte request comme premier paramètre positionnel, qui est ensuite stocké dans l’instance de formulaire à disposition des sous-classes.

confirm_login_allowed(user)

Par défaut, AuthenticationForm rejette les utilisateurs pour lesquels is_active est à False. Vous pouvez modifier ce comportement pour définir une stratégie personnalisée de détermination des utilisateurs qui peuvent se connecter. Pour cela, utilisez un formulaire personnalisé qui hérite de AuthenticationForm et remplace la méthode confirm_login_allowed(). Cette méthode doit générer une exception ValidationError lorsque l’utilisateur donné n’est pas autorisé à se connecter.

Par exemple, pour permettre à tous les utilisateurs de se connecter, indépendamment de leur statut « actif » :

from django.contrib.auth.forms import AuthenticationForm

class AuthenticationFormWithInactiveUsersOkay(AuthenticationForm):
    def confirm_login_allowed(self, user):
        pass

(Dans ce cas, il faudra aussi utiliser un moteur d’authentification qui autorise les utilisateurs inactifs, tel que AllowAllUsersModelBackend.)

Ou pour autoriser uniquement certains utilisateurs actifs à se connecter :

class PickyAuthenticationForm(AuthenticationForm):
    def confirm_login_allowed(self, user):
        if not user.is_active:
            raise forms.ValidationError(
                _("This account is inactive."),
                code='inactive',
            )
        if user.username.startswith('b'):
            raise forms.ValidationError(
                _("Sorry, accounts starting with 'b' aren't welcome here."),
                code='no_b_users',
            )
class PasswordChangeForm

Un formulaire pour permettre à un utilisateur de changer son mot de passe.

class PasswordResetForm

Un formulaire pour générer et envoyer par courriel un lien à usage unique pour réinitialiser le mot de passe d’un utilisateur.

send_mail(subject_template_name, email_template_name, context, from_email, to_email, html_email_template_name=None)

Utilise les paramètres pour envoyer un message EmailMultiAlternatives. Peut être surchargé pour personnaliser la manière dont le courriel est envoyé à l’utilisateur.

Paramètres:
  • subject_template_name – le gabarit pour le sujet du message.
  • email_template_name – le gabarit pour le corps du message.
  • context – contexte transmis aux gabarits subject_template, email_template et html_email_template (s’il ne vaut pas None).
  • from_email – l’adresse électronique de l’expéditeur.
  • to_email – l’adresse électronique du destinataire.
  • html_email_template_name – le gabarit du corps du message HTML ; vaut None par défaut, auquel cas un courriel en texte pur est envoyé.

Par défaut, save() remplit le context avec les mêmes variables que PasswordResetView transmet à son contexte d’envoi de courriel.

class SetPasswordForm

Un formulaire permettant à un utilisateur de changer son mot de passe sans saisir l’ancien mot de passe.

class UserChangeForm

Un formulaire utilisé dans l’interface d’administration pour modifier les données d’un utilisateur et ses permissions.

class UserCreationForm

Un ModelForm pour créer un nouvel utilisateur.

Il possède trois champs : username (du modèle utilisateur), password1 et password2. Il vérifie que password1 et password2 correspondent, valide le mot de passe en utilisant validate_password() et définit le mot de passe de l’utilisateur avec set_password().

Données d’authentification dans les gabarits

L’utilisateur actuellement connecté et ses permissions sont disponibles dans le contexte de gabarit lorsque vous utilisez RequestContext.

Détail technique

Techniquement, ces variables ne sont disponibles dans le contexte de gabarit que si vous utilisez RequestContext et que le processeur de contexte "django.contrib.auth.context_processors.auth" est activé. C’est le cas dans le fichier de réglages par défaut. Pour plus de détails, lisez la documentation de RequestContext.

Utilisateurs

Lors de la génération d’un RequestContext de gabarit, l’utilisateur actuellement connecté, une instance de User ou de AnonymousUser, est stockée dans la variable de gabarit {{ user }}:

{% if user.is_authenticated %}
    <p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
    <p>Welcome, new user. Please log in.</p>
{% endif %}

Cette variable de contexte de gabarit n’est pas disponible si RequestContext n’est pas utilisé.

Permissions

Les permissions de l’utilisateur actuellement connecté sont stockés dans la variable de gabarit {{ perms }}. C’est une instance de django.contrib.auth.context_processors.PermWrapper, un objet mandataire de permissions adapté aux gabarits.

La consultation d’attributs simples de {{ perms }} sous forme de booléen est une méthode mandataire de User.has_module_perms(). Par exemple, pour vérifier si l’utilisateur connecté a au moins une permission dans l’application foo:

{% if perms.foo %}

La consultation d’attributs à deux niveaux de {{ perms }} sous forme de booléen est une méthode mandataire de User.has_perm(). Par exemple, pour vérifier si l’utilisateur connecté a la permission foo.add_vote:

{% if perms.foo.add_vote %}

Voici un exemple plus complet de contrôle de permissions dans un gabarit

{% if perms.foo %}
    <p>You have permission to do something in the foo app.</p>
    {% if perms.foo.add_vote %}
        <p>You can vote!</p>
    {% endif %}
    {% if perms.foo.add_driving %}
        <p>You can drive!</p>
    {% endif %}
{% else %}
    <p>You don't have permission to do anything in the foo app.</p>
{% endif %}

Il est aussi possible de consulter les permissions par des instructions {% if in %}. Par exemple :

{% if 'foo' in perms %}
    {% if 'foo.add_vote' in perms %}
        <p>In lookup works, too.</p>
    {% endif %}
{% endif %}

Gestion des utilisateurs dans le site d’administration

Quand django.contrib.admin et django.contrib.auth sont les deux installés, le site d’administration offre une interface pratique pour afficher et gérer les utilisateurs, les groupes et les permissions. Les utilisateurs peuvent être créés et supprimés comme tout autre modèle Django. Des groupes peuvent être créés et des permissions peuvent être attribuées aux utilisateurs et aux groupes. Les modifications de modèles effectuées dans l’administration par les utilisateurs sont également journalisées et affichées.

Création d’utilisateurs

Vous devriez voir un lien vers « Utilisateurs » dans la section « Auth » de la page d’accueil du site d’administration. La page d’administration « Ajouter un utilisateur » est différente des autres pages d’administration dans la mesure où elle exige que vous saisissiez d’abord un nom d’utilisateur et un mot de passe avant de pouvoir modifier les autres champs de l’utilisateur.

Notez également que si vous voulez qu’un utilisateur puisse créer d’autres utilisateurs dans le site d’administration de Django, vous devez lui attribuer la permission d’ajouter des utilisateurs et de modifier des utilisateurs (c’est-à-dire les permissions « Can add user » et « Can change user »). Si un compte utilisateur a la permission d’ajouter des utilisateurs mais pas de les modifier, ce compte ne pourra pas créer d’utilisateurs. Pourquoi ? Parce que si vous avez la permission d’ajouter des utilisateurs, vous avez le pouvoir de créer des superutilisateurs, qui peuvent à leur tour modifier d’autres utilisateurs. Django exige donc à la fois les permissions « ajout » et « modification » comme légère mesure de sécurité.

Faites attention à la façon dont vous permettez aux utilisateurs de gérer les autorisations. Si vous donnez à un non-superutilisateur la possibilité d’éditer les utilisateurs, cela revient finalement au même que de lui donner un statut de super-utilisateur, car il sera en mesure d’élever les autorisations des utilisateurs, y compris les siennes !

Modification des mots de passe

Les mots de passe des utilisateurs ne sont pas affichés dans le site d’administration (ni stockés dans la base de données), mais les détails de stockage des mots de passe sont visibles. Ces informations contiennent un lien vers le formulaire de changement de mot de passe permettant aux administrateurs de changer les mots de passe des utilisateurs.

Back to Top