[PYTHON] Implémentation de la fonction d'authentification du modèle utilisateur personnalisé dans Django REST Framework à l'aide de djoser

Qu'est-ce que Djoser

djoser est une bibliothèque qui prend en charge l'authentification et l'enregistrement des utilisateurs de base sur le Django REST Framework. Il peut également être utilisé pour des modèles personnalisés et est conçu pour une architecture qui s'adapte mieux à l'application à page unique (SPA) plutôt que de réutiliser le code Django.

Cette fois, j'écrirai sur l'implémentation de la fonction d'authentification la plus simple de djoser. Notez que cette authentification ne doit pas être réellement utilisée pour des raisons de sécurité, et il existe des paramètres de sécurité plus forts tels que l'authentification JWT ci-dessous. Je vais l'introduire comme une simple certification jusqu'au dernier.

Le code source est ici

Tous les éléments suivants peuvent être utilisés comme points de terminaison après l'installation.

/users/ /users/me/ /users/confirm/ /users/resend_activation/ /users/set_password/ /users/reset_password/ /users/reset_password_confirm/ /users/set_username/ /users/reset_username/ /users/reset_username_confirm/ /token/login/ (Token Based Authentication) /token/logout/ (Token Based Authentication) /jwt/create/ (JSON Web Token Authentication) /jwt/refresh/ (JSON Web Token Authentication) /jwt/verify/ (JSON Web Token Authentication) Getting started

J'ai écrit d'autres articles liés à djoser.

Cette fois, nous implémenterons l'authentification des utilisateurs à l'aide de l'authentification JWT.

Comment utiliser

Le flux jusqu'au milieu est le même que l'heure d'authentification JWT, et les principaux changements sont l'écriture de models.py par vous-même et l'augmentation de certains paramètres.py.

$ pip install -U djoser

Puisque l'authentification JWT est utilisée, simple_jwt doit également être utilisé.

$ pip install -U djangorestframework_simplejwt

Tout d'abord, faites un projet

$ django-admin startproject djoser_customuser

Entrez dans le projet

$ cd djoser_customuser

Créez une application.

$ django-admin startapp accounts

Ensuite, nous allons configurer Django.

setings.py



from datetime import timedelta # add

   .........

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework', # add
    'djoser', # add
    'accounts' # add
]

# add
SIMPLE_JWT = {
    #Définir le jeton sur JWT
    'AUTH_HEADER_TYPES':('JWT'),
    #Définition de la durée du jeton
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60)
}

# add
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),
}

# add
AUTH_USER_MODEL = 'user.accounts'

urls.py


from django.contrib import admin
from django.urls import path,include #add

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/auth/',include('djoser.urls')), #add
    path('api/auth/',include('djoser.urls.jwt')), #add
]

À partir de là, j'écrirai un modèle d'utilisateur personnalisé pour la pièce qui est très différente de l'article de certification JWT. En ce qui concerne la raison pour laquelle nous utilisons un modèle utilisateur personnalisé au lieu du modèle par défaut, en général, le modèle utilisateur fourni par défaut n'est pas suffisant lors de la création de l'application Web que nous voulons, et le développement a progressé. Puisqu'il est difficile de modifier le modèle utilisateur ultérieurement, il est souhaitable de concevoir un modèle utilisateur personnalisé qui répond aux exigences à l'avance.

De plus, Django est livré avec deux classes, la classe "AbstractUser" et la "AbstractBaseUser", qui sont incluses par défaut.

Comme il est similaire à la classe User, il est facile à utiliser car il nécessite moins de codage. Par conséquent, il est souvent utilisé lors de l'ajout d'attributs uniquement.

Il nécessite plus de codage car vous devez écrire le nom d'utilisateur et d'autres attributs, mais il est plus flexible que AbstractUser.

Généralement, il présente les caractéristiques ci-dessus. Cette fois, nous utiliserons "AbstactBaseUser".

models.py


from django.db import models

# add
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.validators import UnicodeUsernameValidator
from django.utils import timezone
from django.core.mail import send_mail
from django.contrib.auth.base_user import BaseUserManager

# add
class UserManager(BaseUserManager):
    use_in_migrations = True

    def _create_user(self, username, email, password, **extra_fields):
        """
        Create and save a user with the given username, email, and password.
        """
        if not username:
            raise ValueError('The given username must be set')
        email = self.normalize_email(email)
        username = self.model.normalize_username(username)
        user = self.model(username=username, email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, username, email=None, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(username, email, password, **extra_fields)

    def create_superuser(self, username, email, password, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(username, email, password, **extra_fields)

class User(AbstractBaseUser, PermissionsMixin):
    """
    An abstract base class implementing a fully featured User model with
    admin-compliant permissions.
    Username and password are required. Other fields are optional.
    """
    username_validator = UnicodeUsernameValidator()

    username = models.CharField(
        _('username'),
        max_length=150,
        unique=True,
        help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
        validators=[username_validator],
        error_messages={
            'unique': _("A user with that username already exists."),
        },
    )
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=150, blank=True)
    email = models.EmailField(_('email address'), blank=True,unique=True)
    profile = models.CharField(_('profile'), max_length=255, blank=True) # add
    is_staff = models.BooleanField(
        _('staff status'),
        default=False,
        help_text=_('Designates whether the user can log into this admin site.'),
    )
    is_active = models.BooleanField(
        _('active'),
        default=True,
        help_text=_(
            'Designates whether this user should be treated as active. '
            'Unselect this instead of deleting accounts.'
        ),
    )
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)


    objects = UserManager()

    EMAIL_FIELD = 'email' # fix
    USERNAME_FIELD = 'email' # fix
    REQUIRED_FIELDS = ['username'] # fix

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')

    def clean(self):
        super().clean()
        self.email = self.__class__.objects.normalize_email(self.email)

    def get_full_name(self):
        """
        Return the first_name plus the last_name, with a space in between.
        """
        full_name = '%s %s' % (self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        """Return the short name for the user."""
        return self.first_name

    def email_user(self, subject, message, from_email=None, **kwargs):
        """Send an email to this user."""
        send_mail(subject, message, from_email, [self.email], **kwargs)

Après cela, le flux est exactement le même que celui de l'article JWT. Cependant, il y a une différence, d'abord dans models.py

models.py


EMAIL_FIELD = 'email' # fix
USERNAME_FIELD = 'email' # fix
REQUIRED_FIELDS = ['username'] # fix

Jusqu'à présent, le nom d'utilisateur était un élément obligatoire lors de la création d'un utilisateur, mais cette fois, l'e-mail est un élément obligatoire. Lors de l'utilisation d'un service Web, le courrier électronique doit être un élément obligatoire plutôt qu'un nom d'utilisateur. Ce sont également les avantages de l'utilisation d'utilisateurs personnalisés.

Migrez et créez un super utilisateur.

$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py createsuperuser
Email address: [email protected]
Username: Admin
Password:*********** 

Commencez sur l'hôte local et spécifiez http://localhost:8000/api/auth Accéder.

$ python manage.py runserver

スクリーンショット 2020-04-21 0.41.16.png

Et http://localhost:8000/api/auth/users/ Lorsque vous accédez

スクリーンショット 2020-04-21 0.41.25.png

Les informations utilisateur ne peuvent pas être obtenues car elles ne sont toujours pas authentifiées. Alors, comme la dernière fois, pour obtenir un jeton http://localhost:8000/api/auth/jwt/create/ Accédez, entrez la valeur du super utilisateur que vous avez enregistré précédemment et appuyez sur POST en bas à droite.

スクリーンショット 2020-04-21 0.41.41.png

Ensuite, le jeton suivant sera émis et le jeton d'accès en bas sera copié.

スクリーンショット 2020-04-21 0.42.10.png

Obtenons réellement les informations utilisateur en utilisant la commande curl.

curl -LX GET http://127.0.0.1:8000/api/auth/users/me/ -H 'Authorization: JWT xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

(Entrez le jeton dans xxxx)

Puis

{"username":"Admin","id":1,"email":"[email protected]"}

Les informations utilisateur que vous avez enregistrées précédemment seront renvoyées.

Recommended Posts

Implémentation de la fonction d'authentification du modèle utilisateur personnalisé dans Django REST Framework à l'aide de djoser
Implémentation de la fonction d'authentification dans Django REST Framework à l'aide de djoser
Implémentation de la fonction d'authentification JWT dans Django REST Framework à l'aide de djoser
Plus de nouvelles méthodes d'authentification des utilisateurs avec Django REST Framework
Créer une API autour de l'authentification des utilisateurs avec Django REST Framework
Implémenter un modèle utilisateur personnalisé dans Django
Implémentation de CRUD à l'aide de l'API REST avec Python + Django Rest framework + igGrid
Comment gérer les caractères déformés dans json de Django REST Framework
Implémenter des URL hiérarchiques avec des routeurs imbriqués drf dans le framework Django REST
Framework Django REST avec Vue.js
Connectez-vous avec Django Rest Framework
Comment écrire une validation personnalisée dans Django REST Framework
Implémentation de la fonction de connexion dans Django
[Django] Utiliser MessagePack avec le framework Django REST
Créer une API RESTful avec Django Rest Framework
Suppression logique dans Django, DRF (Django REST Framework)
Comprendre la commodité de Django Rest Framework
CRUD GET avec Nuxt & Django REST Framework ②
CRUD POST avec Nuxt & Django REST Framework
CRUD GET avec Nuxt & Django REST Framework ①
CRUD PUT, DELETE avec Nuxt & Django REST Framework
Je souhaite créer une API qui retourne un modèle avec une relation récursive dans Django REST Framework
Implémenter la fonctionnalité de connexion JWT dans le framework Django REST
Comment utiliser fixture dans Django pour saisir des exemples de données associés au modèle utilisateur
Créer une application Todo avec Django REST Framework + Angular
Implémentation d'estimation la plus probable du modèle de sujet en python
Essayez de créer une application Todo avec le framework Django REST
Lorsque vous souhaitez filtrer avec le framework Django REST
List, méthode pour les ressources imbriquées dans le framework Django REST
Implémentation d'estimation bayésienne de variante du modèle de sujet en python
Modifications du modèle dans Django
Bases du framework Django REST
Astuces Django Rest Framework
[Django] Gérez les paramètres comme l'écriture dans settings.py avec un modèle
Implémentation facile de la fonction de paiement par carte de crédit avec PAY.JP [Django]
Créer une fonction d'authentification à l'aide de django-allauth et CustomUser dans Django
Bloc d'achoppement du framework Django REST
Implémentation du tri rapide en Python
Exploration avec Python et Twitter API 2-Implémentation de la fonction de recherche d'utilisateurs
Créer une API REST pour faire fonctionner dynamodb avec le Framework Django REST