Django-注册/登录/登出类视图
Django-注册/登录/登出类视图

Django-注册/登录/登出类视图

喵喵CRM很多地方写得乱七八糟,能用但是代码看起来实在很糟糕。

最近在写权限模块,想和之前客户模块对比对比,然而一对比才发现,之前写的简直就是一坨。而且之前部分地方是一边学一边写的,很冗余。遂打算重构下部分地方,主要是:登录登出、文件目录整理、视图重构、代码注释补充、程序主页、路由调整等,此外,为了进一步贯彻前后端分离逻辑,Django里面的templates页面就都给删除了,后续测试主要采用Apifox进行(之前一直没咋用,觉得页面直观一些。今天仔细用了一下,发现……真的方便)。

之前的注册、登录、登出是放在customer模块下面的,现在给独立出来,此外全部改用DRF,实现前后端分离。

注册

序列化器

from rest_framework import serializers
from django.contrib.auth.models import User

class RegisterSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True)

    class Meta:
        model = User
        fields = ['username', 'password', 'first_name', 'last_name']

    def create(self, validated_data):
        """
        使用create_user覆写create函数,密码加密。
        """
        user = User.objects.create_user(**validated_data)
        return user

先介绍下父类:serializers.ModelSerializer,几乎所有的序列化都会用到。ModelSerializer 是 DRF 提供的一个类,可以(1)自定义方法(如 create)来实现更细粒度的控制。(2)自动处理模型字段的验证和序列化。(3)提供默认的 createupdate 方法,适配模型实例的创建和更新。

这儿整体逻辑比较简单,需要注意的是密码特殊处理,write_only保证了密码只可POST接收值,不在GET中响应。而create方法重写,换成User.object.create_user可以保证密码哈希加密。

此外,DRF会默认一些安全措施:(1)身份验证机制,支持SessionAuthentication和TokenAuthentication。(2)CSRF保护,不过通常通过token认证来代替CSRF验证。不过在暴力破解、XSS攻击等方面仍有些欠缺。

有趣的是**validated_data这个写法,就是把 validated_data 这个字典里的每个键值对拆开,作为关键字参数传给 create_user 方法。

validated_data = {'username': 'john', 'password': 'securepassword'}
user = User.objects.create_user(**validated_data)
# 相当于:
user = User.objects.create_user(username='john', password='securepassword')

视图

from django.shortcuts import render
from django.contrib.auth import authenticate
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from .serializers import RegisterSerializer
from rest_framework_simplejwt.tokens import RefreshToken
from django.views import View

class RegisterView(APIView):
    def post(self, request):
        serializer = RegisterSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({"message": "注册成功,请登录!"}, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

简单明了,获取数据、验证、存储。APIView后续会具体对比分析下,这儿先默认使用。

登录

登录仅仅需要对比下账户和密码,无需序列化器。

视图

class LoginView(APIView):
    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')

        user = authenticate(username=username, password=password)
        if user is not None:
            refresh = RefreshToken.for_user(user)
            return Response({
                'refresh': str(refresh),
                'access': str(refresh.access_token),
            })
        return Response({"error": "用户名或密码错误"}, status=status.HTTP_401_UNAUTHORIZED)

authenticate可以检查登录名和密码是否匹配,不匹配返回NoneRefreshToken则是DRF的一个扩展库, Simple JWT 的一部分。Simple JWT 是专门用于生成和验证 JSON Web Tokens (JWT)。

JWT是一种用于在网络应用环境中安全地传递声明的开放标准,它通常用于身份认证和信息交换。JWT 是一种自包含的令牌格式,意味着它包含了所有用户认证和验证所需的信息,而无需查询数据库。简单来说,一个用于前后端认证的工具,省的每次访问都去查询数据库,同时具备一定的安全性。这儿会有两个token,refreshaccess,一个稍微长期、一个短期。access失效了就用refresh再去要个access

登出

视图

class LogoutView(APIView):
    def post(self, request):
        response = Response({"message": "登出成功"})
        response.delete_cookie('access_token')
        return response

路由

from django.urls import path
from .views import RegisterView, LoginView, LogoutView


urlpatterns = [
    path('register/', RegisterView.as_view(), name='register'),
    path('login/', LoginView.as_view(), name='login'),
    path('logout/', LogoutView.as_view(), name='logout'),
]

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注