用DRF进行会话认证

简要的概述

以下是在Python的Django REST Framework中实现会话认证的方法,附带步骤进行介绍。

会话认证是什么?

会话认证是Web应用程序中用于管理用户登录状态的一种认证方式。在会话认证中,用户登录后,服务器端会创建一个会话,并将登录信息保存在该会话中。之后,在会话过期前,每当用户发送请求时,服务器端会使用请求中包含的会话ID来识别会话对象,并确认用户是否已登录。

Django REST Framework中的会话认证方式。

所有版本

Python: 3.10
Django:4.1.4
Docker: 20.10.11
docker-compose: 2.2.1

Python:3.10版本
Django:4.1.4版本
Docker:20.10.11版本
docker-compose:2.2.1版本

操作步骤

Django的基本环境设置

请参考Qiita这篇文章中的”虚拟环境搭建”和”Django项目创建”部分。

这次,我们将项目名定为session_auth。

会话认证的实施步骤

我将创建一个管理用户信息的应用程序。

(venv) session_auth % python manage.py startapp account

创建自定义用户。

from django.db import models
from django.contrib.auth.models import (BaseUserManager,
                                        AbstractBaseUser,
                                        PermissionsMixin)
from django.utils.translation import gettext_lazy as _

class UserManager(BaseUserManager):
    def _create_user(self, email, username, password, **extra_fields):
        email = self.normalize_email(email)
        user = self.model(email=email, username=username, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        user.full_clean()

        return user

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

    def create_superuser(self, email, username, password, **extra_fields):
        extra_fields['is_active'] = True
        extra_fields['is_staff'] = True
        extra_fields['is_superuser'] = True
        return self._create_user(
            email=email,
            username=username,
            password=password,
            **extra_fields,
        )

class User(AbstractBaseUser, PermissionsMixin):

    username = models.CharField(
        verbose_name=_("username"),
        unique=True,
        max_length=150
    )
    email = models.EmailField(
        verbose_name=_("Email Address"),
        unique=True
    )
    age = models.IntegerField(
        verbose_name=_("age"),
        null=True,
        blank=True
    )
    is_superuser = models.BooleanField(
        verbose_name=_("is_superuer"),
        default=False
    )
    is_staff = models.BooleanField(
        _('staff status'),
        default=False,
    )
    is_active = models.BooleanField(
        _('active'),
        default=True,
    )

    objects = UserManager()

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email']

    def __str__(self):
        return self.username

修改settings.py。

...

ALLOWED_HOSTS = ["*"] # ワイルドカードを追加

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework', # djangorestframeworkを追加
    'account' # 作成したaccountアプリを追加
]

...

AUTH_USER_MODEL = "account.User" # accountアプリのUserモデルをデフォルトで使用する認証ユーザーモデルとして設定する

...

SESSION_ENGINE = 'django.contrib.sessions.backends.db' # セッションを何で保存するかを指定する。この場合はDBで管理する。

为了在管理界面上确认会话,我们需要编辑admin.py文件。

from django.contrib import admin
from django.contrib.sessions.models import Session

admin.site.register(Session)

如果你能做到这一点,那么我会进行迁移。

(venv) session_auth % python manage.py makemigrations
(venv) session_auth % python manage.py migrate

在这里,我们将创建一个超级用户并确认能够登录管理界面。

(venv) session_auth % python manage.py createsuperuser
Username (leave blank to use 'testuser'): testuser
Email address: test@example.com
Password: 
Password (again):
Superuser created successfully.

启动开发用服务器。

(venv) session_auth % python manage.py runserver

使用浏览器打开 http://127.0.0.1:8000/admin/,并访问管理页面。

Screen Shot 2023-02-21 at 20.34.09.png

请使用刚刚创建的超级用户账号信息进行登录。

Screen Shot 2023-02-21 at 20.34.22.png

当查看Sessions时,可以确认已创建了1个会话。

Screen Shot 2023-02-21 at 20.35.08.png

如果确认完成了,请先注销一下。

接下来,我们将创建serializers.py。

from rest_framework import serializers
from .models import User


class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = "__all__"

我要编辑views.py文件。

from rest_framework import viewsets
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated

from .models import User
from .serializers import UserSerializer

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    authentication_classes = (SessionAuthentication,)
    permission_classes = (IsAuthenticated, )

将UserViewSet的authentication_classes设置为SessionAuthentication,
将permission_classes设置为IsAuthenticated。
这样,访问UserViewsSet将需要进行会话认证。
顺便一提,viewsets.ModelViewSet是一个非常方便的视图,它可以集中管理列表获取、详细获取、创建、更新和删除的功能。
(本例中只使用列表获取功能来进行认证的确认。)
为了能访问UserViewSet,我们需要创建urls.py并更新project/urls.py。

from django.urls import include, path
from rest_framework.routers import DefaultRouter
from .views import UserViewSet

router = DefaultRouter()
router.register(r'account', UserViewSet)

urlpatterns = [
    path('', include(router.urls))
]
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/', include('account.urls')), # account/urls.pyを指定
]

如果访问/api/v1/account,会执行会话认证,并且如果认证成功,应该能够获取用户信息!

确认动作

让我们来确认一下吧!

首先,请尝试访问http://127.0.0.1:8000/api/v1/account。

session-auth-1.png
session-auth-2.png
session-auth-3.png

成功获取到用户信息!?

我們結束了對DRF會話驗證實現方法的解說。

非常感谢!

广告
将在 10 秒后关闭
bannerAds