---
title: "Utilisation du système d’authentification de Django"
version: 2.1
locale: fr
source: https://docs.djangoproject.com/fr/2.1/topics/auth/default/
canonical: https://djangodocs.dev/fr/2.1/topics/auth/default/
---
# 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](/fr/2.1/topics/auth/customizing/) 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`](/fr/2.1/ref/contrib/auth/#id1) 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'`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.User.is_superuser)) ou les membres des équipes d’administration du site ( [`'staff'`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.User.is_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 :

- [`username`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.User.username)
- [`password`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.User.password)
- [`email`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.User.email)
- [`first_name`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.User.first_name)
- [`last_name`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.User.last_name)

Consultez la [`documentation complète de l'API`](/fr/2.1/ref/contrib/auth/#id1) 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()`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.UserManager.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](#auth-admin).

### Création de superutilisateurs

Les superutilisateurs peuvent être créés à l’aide de la commande [`createsuperuser`](/fr/2.1/ref/django-admin/#django-admin-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`](/fr/2.1/ref/django-admin/#cmdoption-createsuperuser-username) ou [`--email`](/fr/2.1/ref/django-admin/#cmdoption-createsuperuser-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](/fr/2.1/topics/auth/passwords/) 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*`](/fr/2.1/ref/django-admin/#django-admin-changepassword) 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()`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.User.set_password):

```pycon
>>> 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](#auth-admin).

Django fournit également des [vues](#built-in-auth-views) et des [formulaires](#built-in-auth-forms) 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](#session-invalidation-on-password-change) pour plus de détails.

### Authentification des utilisateurs

#### `authenticate(request=None, \**credentials)`

Utilisez [`authenticate()`](#django.contrib.auth.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](/fr/2.1/topics/auth/customizing/#authentication-backends) et renvoie un objet [`User`](/fr/2.1/ref/contrib/auth/#id1) si l’authentification est valide pour un des moteurs. Si aucun moteur n’accepte l’authentification ou si un moteur génère [`PermissionDenied`](/fr/2.1/ref/exceptions/#django.core.exceptions.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`](/fr/2.1/ref/request-response/#django.http.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`](/fr/2.1/ref/middleware/#django.contrib.auth.middleware.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`](#django.contrib.auth.views.LoginView).

## Permissions et autorisations

Django contient un système simple 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()`](/fr/2.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.has_view_permission), [`has_add_permission()`](/fr/2.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.has_add_permission), [`has_change_permission()`](/fr/2.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.has_change_permission) et [`has_delete_permission()`](/fr/2.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.has_delete_permission) fournies par la classe [`ModelAdmin`](/fr/2.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin), il est possible de personnaliser les permissions pour différentes instances d’objets du même type.

Les objets [`User`](/fr/2.1/ref/contrib/auth/#id1) possèdent deux champs plusieurs-à-plusieurs : `groups` et `user_permissions`. Les objets [`User`](/fr/2.1/ref/contrib/auth/#id1) peuvent accéder à leurs objets liés de la même façon que pour tout autre [modèle Django](/fr/2.1/topics/db/models/):

```
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`](/fr/2.1/ref/settings/#std-setting-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`](/fr/2.1/ref/django-admin/#django-admin-migrate); au premier lancement de `migrate` après l’ajout de `django.contrib.auth` à [`INSTALLED_APPS`](/fr/2.1/ref/settings/#std-setting-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`](/fr/2.1/ref/django-admin/#django-admin-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`](/fr/2.1/ref/signals/#django.db.models.signals.post_migrate)).

En supposant qu’une application ait l’attribut [`app_label`](/fr/2.1/ref/models/options/#django.db.models.Options.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`](/fr/2.1/ref/contrib/auth/#id3) est rarement accédé directement.

### Groupes

Les modèles [`django.contrib.auth.models.Group`](/fr/2.1/ref/contrib/auth/#id6) 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](/fr/2.1/topics/auth/customizing/#custom-permissions) 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`](/fr/2.1/ref/contrib/auth/#id1) par son attribut `user_permissions` ou à un [`Group`](/fr/2.1/ref/contrib/auth/#id6) par son attribut `permissions`.

### Mise en cache des permissions

Le moteur [`ModelBackend`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.backends.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

    ...
```

## Authentification dans les requêtes Web

Django utilise les [sessions](/fr/2.1/topics/http/sessions/) et le système de middleware pour brancher le système d’authentification dans les [`objets requête`](/fr/2.1/ref/request-response/#django.http.HttpRequest).

Un attribut [`request.user`](/fr/2.1/ref/request-response/#django.http.HttpRequest.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`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.AnonymousUser), sinon il s’agira d’une instance de [`User`](/fr/2.1/ref/contrib/auth/#id1).

Vous pouvez les différencier par la méthode [`is_authenticated`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.User.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()`](#django.contrib.auth.login).

#### `login(request, user, backend=None)`

Pour connecter un utilisateur à partir d’une vue, utilisez  [`login()`](#django.contrib.auth.login). Cette fonction accepte un objet [`HttpRequest`](/fr/2.1/ref/request-response/#django.http.HttpRequest) et un objet [`User`](/fr/2.1/ref/contrib/auth/#id1). [`login()`](#django.contrib.auth.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()`](#django.contrib.auth.authenticate) et [`login()`](#django.contrib.auth.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](/fr/2.1/topics/auth/customizing/#authentication-backends) 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()`](#django.contrib.auth.authenticate) et [`login()`](#django.contrib.auth.login): [`authenticate()`](#django.contrib.auth.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`](/fr/2.1/ref/settings/#std-setting-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`](/fr/2.1/ref/settings/#std-setting-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()`](#django.contrib.auth.login), utilisez [`django.contrib.auth.logout()`](#django.contrib.auth.logout) depuis la vue. Cette fonction accepte un objet [`HttpRequest`](/fr/2.1/ref/request-response/#django.http.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()`](#django.contrib.auth.logout) ne signale pas d’erreur si l’utilisateur n’était pas connecté.

Lorsque vous appelez [`logout()`](#django.contrib.auth.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()`](#django.contrib.auth.logout).

### Restriction d’accès aux utilisateurs connectés

#### La manière brute

La manière simple et directe de limiter l’accès à certaines pages est de vérifier [`request.user.is_authenticated`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.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()`](#django.contrib.auth.decorators.login_required) bien pratique :

```
from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
    ...
```

[`login_required()`](#django.contrib.auth.decorators.login_required) effectue ceci :

- Si l’utilisateur n’est pas connecté, il redirige vers [`settings.LOGIN_URL`](/fr/2.1/ref/settings/#std-setting-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()`](#django.contrib.auth.decorators.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()`](#django.contrib.auth.decorators.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`](/fr/2.1/ref/settings/#std-setting-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`](/fr/2.1/ref/settings/#std-setting-LOGIN_URL) accepte également des noms de fonction vue et des [motifs d’URL nommés](/fr/2.1/topics/http/urls/#naming-url-patterns). 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`](/fr/2.1/ref/settings/#std-setting-AUTHENTICATION_BACKENDS) par défaut rejette les utilisateurs inactifs.

> **See also**
>
> 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()`](/fr/2.1/ref/contrib/admin/#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](/fr/2.1/topics/class-based-views/), 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`](#django.contrib.auth.mixins.AccessMixin.raise_exception).

Vous pouvez définir n’importe lequel des paramètres de [`AccessMixin`](#django.contrib.auth.mixins.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`](/fr/2.1/ref/settings/#std-setting-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.

La manière simple est d’effectuer le test sur [`request.user`](/fr/2.1/ref/request-response/#django.http.HttpRequest.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()`](#django.contrib.auth.decorators.user_passes_test) requiert un paramètre : un exécutable acceptant un objet [`User`](/fr/2.1/ref/contrib/auth/#id1) et renvoyant `True` si l’utilisateur est autorisé à voir la page. Notez que  [`user_passes_test()`](#django.contrib.auth.decorators.user_passes_test) ne contrôle pas d’office que l’objet [`User`](/fr/2.1/ref/contrib/auth/#id1) n’est pas anonyme.

[`user_passes_test()`](#django.contrib.auth.decorators.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`](/fr/2.1/ref/settings/#std-setting-LOGIN_URL).

**`redirect_field_name`**

  Comme pour [`login_required()`](#django.contrib.auth.decorators.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](/fr/2.1/topics/class-based-views/), 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`](#django.contrib.auth.mixins.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()`](#django.contrib.auth.mixins.UserPassesTestMixin.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()`](#django.contrib.auth.decorators.permission_required):

```
from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote')
def my_view(request):
    ...
```

Comme pour la méthode [`has_perm()`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.User.has_perm), les noms de permission ont la forme `"<étiquette application>.<code permission>"` (par ex. `polls.can_vote` 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()`](#django.contrib.auth.decorators.permission_required) accepte également un paramètre facultatif `login_url`:

```
from django.contrib.auth.decorators import permission_required

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

Comme pour le décorateur [`login_required()`](#django.contrib.auth.decorators.login_required), la valeur par défaut de `login_url` est [`settings.LOGIN_URL`](/fr/2.1/ref/settings/#std-setting-LOGIN_URL).

Si le paramètre `raise_exception` est présent, le décorateur génère une exception [`PermissionDenied`](/fr/2.1/ref/exceptions/#django.core.exceptions.PermissionDenied) (permission refusée), déclenchant la  [vue 403 (HTTP Forbidden)](/fr/2.1/ref/views/#http-forbidden-view) 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()`](#django.contrib.auth.decorators.login_required):

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

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

Ceci évite aussi une boucle de redirection lorsque `redirect_authenticated_user=True` dans [`LoginView`](#django.contrib.auth.views.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](/fr/2.1/ref/class-based-views/), 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.can_vote'
    # Or multiple of permissions:
    permission_required = ('polls.can_open', 'polls.can_edit')
```

Vous pouvez définir n’importe lequel des paramètres de [`AccessMixin`](#django.contrib.auth.mixins.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()`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.User.has_perms) avec la liste des permissions renvoyées par [`get_permission_required()`](#django.contrib.auth.mixins.PermissionRequiredMixin.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](/fr/2.1/ref/class-based-views/), 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`](#django.contrib.auth.mixins.AccessMixin.raise_exception).

> **Changed in Django 2.1**
>
> Dans les anciennes versions, les utilisateurs authentifiés qui n’avaient pas les permissions suffisantes étaient redirigés vers la page de connexion (ce qui produisait une boucle) au lieu de recevoir la réponse d’accès interdit HTTP 403.

#### `class AccessMixin`

#### `login_url`

Valeur de renvoi par défaut de [`get_login_url()`](#django.contrib.auth.mixins.AccessMixin.get_login_url). Contient `None` par défaut auquel cas [`get_login_url()`](#django.contrib.auth.mixins.AccessMixin.get_login_url) se rabat sur le contenu de [`settings.LOGIN_URL`](/fr/2.1/ref/settings/#std-setting-LOGIN_URL).

#### `permission_denied_message`

Valeur de renvoi par défaut de [`get_permission_denied_message()`](#django.contrib.auth.mixins.AccessMixin.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()`](#django.contrib.auth.mixins.AccessMixin.get_redirect_field_name). Contient `"next"` par défaut.

#### `raise_exception`

Si cet attribut est défini à `True`, une exception [`PermissionDenied`](/fr/2.1/ref/exceptions/#django.core.exceptions.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`](#django.contrib.auth.mixins.AccessMixin.login_url) le cas échéant, sinon [`settings.LOGIN_URL`](/fr/2.1/ref/settings/#std-setting-LOGIN_URL).

#### `get_permission_denied_message()`

Lorsque [`raise_exception`](#django.contrib.auth.mixins.AccessMixin.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`](#django.contrib.auth.mixins.AccessMixin.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`](#django.contrib.auth.mixins.AccessMixin.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`](/fr/2.1/ref/exceptions/#django.core.exceptions.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`](/fr/2.1/ref/settings/#std-setting-AUTH_USER_MODEL) hérite de [`AbstractBaseUser`](/fr/2.1/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser) ou implémente sa propre méthode [`get_session_auth_hash()`](/fr/2.1/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash),  les sessions authentifiées comprendront la valeur de hachage renvoyée par cette fonction. Dans le cas d’un [`AbstractBaseUser`](/fr/2.1/topics/auth/customizing/#django.contrib.auth.models.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`](#django.contrib.auth.views.PasswordChangeView) et `user_change_password` du module [`django.contrib.auth`](/fr/2.1/topics/auth/#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()`](#django.contrib.auth.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()`](/fr/2.1/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash) se base sur [`SECRET_KEY`](/fr/2.1/ref/settings/#std-setting-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](#built-in-auth-forms), 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](#all-authentication-views).

#### 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](/fr/2.1/topics/http/urls/) 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](/fr/2.1/topics/class-based-views/) 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](#using-the-views).

#### `class LoginView`

**Nom d’URL :** `login`

Consultez la [documentation sur les URL](/fr/2.1/topics/http/urls/) 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 simple classe de formulaire) à utiliser pour l’authentification. Sa valeur par défaut est [`AuthenticationForm`](#django.contrib.auth.forms.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`.

  > **Warning**
  >
  > 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](https://robinlinus.github.io/socialmedia-leak/) », 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()`](#django.contrib.auth.decorators.permission_required) est utilisé sans que le paramètre `raise_exception` ne soit indiqué.
- `success_url_allowed_hosts`: un ensemble [`set`](https://docs.python.org/3/library/stdtypes.html#set) d’hôtes, en plus de [`request.get_host()`](/fr/2.1/ref/request-response/#django.http.HttpRequest.get_host), qui sont sûrs comme cible de redirection après la connexion. L’ensemble  [`set`](https://docs.python.org/3/library/stdtypes.html#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`](/fr/2.1/ref/settings/#std-setting-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`](/fr/2.1/ref/forms/api/#django.forms.Form) représentant le formulaire [`AuthenticationForm`](#django.contrib.auth.forms.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`](/fr/2.1/ref/contrib/sites/#django.contrib.sites.models.Site) actuel, selon le réglage [`SITE_ID`](/fr/2.1/ref/settings/#std-setting-SITE_ID). Si l’application `site` n’est pas installée, il s’agira d’une instance de [`RequestSite`](/fr/2.1/ref/contrib/sites/#django.contrib.sites.requests.RequestSite) qui détecte le nom du site et son domaine à partir de l’objet [`HttpRequest`](/fr/2.1/ref/request-response/#django.http.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']`](/fr/2.1/ref/request-response/#django.http.HttpRequest.META). Pour plus d’informations sur les sites, voir [L’infrastructure des « sites »](/fr/2.1/ref/contrib/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`:

```html+django
{% 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](/fr/2.1/topics/auth/customizing/)), 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`](/fr/2.1/ref/settings/#std-setting-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`](https://docs.python.org/3/library/stdtypes.html#set) d’hôtes, en plus de [`request.get_host()`](/fr/2.1/ref/request-response/#django.http.HttpRequest.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`](/fr/2.1/ref/contrib/sites/#django.contrib.sites.models.Site) actuel, selon le réglage [`SITE_ID`](/fr/2.1/ref/settings/#std-setting-SITE_ID). Si l’application `site` n’est pas installée, il s’agira d’une instance de [`RequestSite`](/fr/2.1/ref/contrib/sites/#django.contrib.sites.requests.RequestSite) qui détecte le nom du site et son domaine à partir de l’objet [`HttpRequest`](/fr/2.1/ref/request-response/#django.http.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']`](/fr/2.1/ref/request-response/#django.http.HttpRequest.META). Pour plus d’informations sur les sites, voir [L’infrastructure des « sites »](/fr/2.1/ref/contrib/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`](/fr/2.1/ref/settings/#std-setting-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.
- `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`](#django.contrib.auth.forms.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`](#django.contrib.auth.forms.PasswordResetForm) et employer l’attribut `form_class`.

Les utilisateurs possédant un mot de passe inutilisable (voir [`set_unusable_password()`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.User.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`](#django.contrib.auth.forms.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.
- `from_email`: une adresse électronique valide. Par défaut, Django utilise [`DEFAULT_FROM_EMAIL`](/fr/2.1/ref/settings/#std-setting-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.

**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`](/fr/2.1/ref/contrib/auth/#id1) 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']`](/fr/2.1/ref/request-response/#django.http.HttpRequest.META). Pour plus d’informations sur les sites, voir [L’infrastructure des « sites »](/fr/2.1/ref/contrib/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) :

```html+django
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`](#django.contrib.auth.views.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`](/fr/2.1/ref/settings/#std-setting-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`](#django.contrib.auth.forms.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.

**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`](/fr/2.1/ref/settings/#std-setting-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`](#module-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é](/fr/2.1/topics/auth/customizing/#auth-custom-user), 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](/fr/2.1/topics/auth/customizing/#custom-users-and-the-built-in-auth-forms).

#### `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`](/fr/2.1/ref/exceptions/#django.core.exceptions.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`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.backends.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`](#django.contrib.auth.views.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`](/fr/2.1/topics/forms/modelforms/#django.forms.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()`](/fr/2.1/topics/auth/passwords/#django.contrib.auth.password_validation.validate_password) et définit le mot de passe de l’utilisateur avec [`set_password()`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.User.set_password).

### Données d’authentification dans les gabarits

L’utilisateur actuellement connecté et ses permissions sont disponibles dans le [contexte de gabarit](/fr/2.1/ref/templates/api/) lorsque vous utilisez [`RequestContext`](/fr/2.1/ref/templates/api/#django.template.RequestContext).

> **Détail technique**
>
> Techniquement, ces variables ne sont disponibles dans le contexte de gabarit que si vous utilisez [`RequestContext`](/fr/2.1/ref/templates/api/#django.template.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](/fr/2.1/ref/templates/api/#subclassing-context-requestcontext).

#### Utilisateurs

Lors de la génération d’un [`RequestContext`](/fr/2.1/ref/templates/api/#django.template.RequestContext) de gabarit, l’utilisateur actuellement connecté, une instance de  [`User`](/fr/2.1/ref/contrib/auth/#id1) ou de [`AnonymousUser`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.AnonymousUser), est stockée dans la variable de gabarit `{{ user }}`:

```html+django
{% 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()`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.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()`](/fr/2.1/ref/contrib/auth/#django.contrib.auth.models.User.has_perm). Par exemple, pour vérifier si l’utilisateur connecté a la permission `foo.can_vote`:

```
{% if perms.foo.can_vote %}
```

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

```html+django
{% if perms.foo %}
    <p>You have permission to do something in the foo app.</p>
    {% if perms.foo.can_vote %}
        <p>You can vote!</p>
    {% endif %}
    {% if perms.foo.can_drive %}
        <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 :

```html+django
{% if 'foo' in perms %}
    {% if 'foo.can_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](/fr/2.1/topics/auth/passwords/) 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.
