[PYTHON] Implementierung der benutzerdefinierten Authentifizierungsfunktion für Benutzermodelle in Django REST Framework mit djoser

Was ist Djoser?

djoser ist eine Bibliothek, die die grundlegende Benutzerauthentifizierung und -registrierung im Django REST Framework unterstützt. Es kann auch für benutzerdefinierte Modelle verwendet werden und ist für eine Architektur konzipiert, die besser zur Single Page Application (SPA) passt, anstatt den Django-Code wiederzuverwenden.

Dieses Mal werde ich über die Implementierung der einfachsten Authentifizierungsfunktion von djoser schreiben. Beachten Sie, dass diese Authentifizierung aus Sicherheitsgründen nicht verwendet werden sollte und es stärkere Sicherheitseinstellungen gibt, wie z. B. die unten stehende JWT-Authentifizierung. Ich werde es als einfache Zertifizierung bis zum letzten einführen.

Der Quellcode ist hier

Alle folgenden Elemente können nach der Installation als Endpunkte verwendet werden.

/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

Ich habe andere Artikel im Zusammenhang mit Djoser geschrieben.

Dieses Mal implementieren wir die Benutzerauthentifizierung mithilfe der JWT-Authentifizierung.

Wie benutzt man

Der Ablauf bis zur Mitte entspricht der JWT-Authentifizierungszeit, und die wichtigsten Änderungen bestehen darin, models.py selbst zu schreiben und einige settings.py zu erhöhen.

$ pip install -U djoser

Da die JWT-Authentifizierung verwendet wird, muss auch simple_jwt verwendet werden.

$ pip install -U djangorestframework_simplejwt

Machen Sie zuerst ein Projekt

$ django-admin startproject djoser_customuser

Gehen Sie in das Projekt hinein

$ cd djoser_customuser

Erstellen Sie eine App.

$ django-admin startapp accounts

Als nächstes werden wir Django konfigurieren.

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 = {
    #Setzen Sie das Token auf JWT
    'AUTH_HEADER_TYPES':('JWT'),
    #Festlegen der Dauer des Tokens
    '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
]

Von hier aus werde ich ein benutzerdefiniertes Benutzermodell für das Teil schreiben, das sich erheblich vom Artikel zur JWT-Zertifizierung unterscheidet. In Bezug darauf, warum wir ein benutzerdefiniertes Benutzermodell anstelle des Standardbenutzermodells verwenden, reicht das Standardbenutzermodell im Allgemeinen nicht aus, um die gewünschte Webanwendung zu erstellen, und die Entwicklung ist fortgeschritten. Da es schwierig ist, das Benutzermodell später zu ändern, ist es wünschenswert, ein benutzerdefiniertes Benutzermodell zu entwerfen, das die Anforderungen im Voraus erfüllt.

Darüber hinaus enthält Django zwei Klassen, die Klasse "AbstractUser" und die Klasse "AbstractBaseUser", die standardmäßig enthalten sind.

Da es der User-Klasse ähnlich ist, ist es einfach zu verwenden, da weniger Codierung erforderlich ist. Daher wird es häufig verwendet, wenn nur Attribute hinzugefügt werden.

Es erfordert mehr Codierung, da Sie den Benutzernamen und andere Attribute schreiben müssen, ist jedoch flexibler als AbstractUser.

Im Allgemeinen weist es die obigen Eigenschaften auf. Dieses Mal werden wir "AbstactBaseUser" verwenden.

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)

Danach ist der Ablauf genau der gleiche wie beim JWT-Artikel. Es gibt jedoch einen Unterschied, zunächst in models.py

models.py


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

Bisher war der Benutzername beim Erstellen eines Benutzers ein erforderliches Element, diesmal ist jedoch E-Mail ein erforderliches Element. Wenn Sie tatsächlich einen Webdienst verwenden, sollte E-Mail ein erforderliches Element und kein Benutzername sein. Dies sind auch die Vorteile der Verwendung von benutzerdefinierten Benutzern.

Migrieren Sie und erstellen Sie einen Superuser.

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

Starten Sie auf dem lokalen Host und geben Sie an http://localhost:8000/api/auth Zugreifen.

$ python manage.py runserver

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

Und http://localhost:8000/api/auth/users/ Wenn Sie zugreifen

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

Benutzerinformationen können nicht abgerufen werden, da sie noch nicht authentifiziert sind. Also, wie beim letzten Mal, um einen Token zu bekommen http://localhost:8000/api/auth/jwt/create/ Greifen Sie zu, geben Sie den Wert des zuvor registrierten Superusers ein und drücken Sie unten rechts auf POST.

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

Dann wird das folgende Token ausgegeben und das Zugriffstoken unten wird kopiert.

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

Lassen Sie uns die Benutzerinformationen mit dem Befehl curl abrufen.

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

(Geben Sie den Token in xxxx ein.)

Dann

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

Die zuvor registrierten Benutzerinformationen werden zurückgegeben.

Recommended Posts

Implementierung der benutzerdefinierten Authentifizierungsfunktion für Benutzermodelle in Django REST Framework mit djoser
Implementierung der Authentifizierungsfunktion in Django REST Framework mit djoser
Implementierung der JWT-Authentifizierungsfunktion in Django REST Framework mit djoser
Weitere neue Benutzerauthentifizierungsmethoden mit Django REST Framework
Erstellen Sie eine API für die Benutzerauthentifizierung mit Django REST Framework
Implementieren Sie ein benutzerdefiniertes Benutzermodell in Django
Implementierung von CRUD mithilfe der REST-API mit Python + Django Rest Framework + igGrid
Wie man mit verstümmelten Charakteren in json von Django REST Framework umgeht
Implementieren Sie hierarchische URLs mit drf-verschachtelten Routern im Django REST-Framework
Django REST Framework mit Vue.js
Melden Sie sich mit dem Django Rest Framework an
So schreiben Sie eine benutzerdefinierte Validierung in Django REST Framework
Implementierung der Login-Funktion in Django
[Django] Verwenden Sie MessagePack mit dem Django REST-Framework
Erstellen Sie eine RESTful-API mit dem Django Rest Framework
Logisches Löschen in Django, DRF (Django REST Framework)
Verstehen Sie den Komfort des Django Rest Framework
CRUD GET mit Nuxt & Django REST Framework ②
CRUD POST mit Nuxt & Django REST Framework
CRUD GET mit Nuxt & Django REST Framework ①
CRUD PUT, DELETE mit Nuxt & Django REST Framework
Ich möchte eine API erstellen, die ein Modell mit einer rekursiven Beziehung im Django REST Framework zurückgibt
Implementieren Sie die JWT-Anmeldefunktion im Django REST-Framework
Verwendung von Fixture in Django zur Eingabe von Beispieldaten für das Benutzermodell
Erstellen Sie eine Todo-App mit Django REST Framework + Angular
Höchstwahrscheinlich Schätzungsimplementierung des Themenmodells in Python
Lassen Sie uns eine Todo-App mit dem Django REST-Framework erstellen
Wenn Sie mit dem Django REST-Framework filtern möchten
Listenmethode für verschachtelte Ressourcen im Django REST-Framework
Implementierung der Bayes'schen Varianzschätzung des Themenmodells in Python
Modelländerungen in Django
Grundlagen des Django REST-Frameworks
Tipps zum Django Rest Framework
[Django] Verwalten Sie Einstellungen wie das Schreiben in settings.py mit einem Modell
Einfache Implementierung der Kreditkartenzahlungsfunktion mit PAY.JP [Django]
Erstellen Sie eine Authentifizierungsfunktion mit django-allauth und CustomUser in Django
Django REST Framework Stolperstein
Implementierung der schnellen Sortierung in Python
Crawlen mit Python und Twitter API 2-Implementierung der Benutzersuchfunktion
Erstellen Sie eine REST-API, um dynamodb mit dem Django REST Framework zu betreiben