• 个人博客系列-后端项目-用户验证(5)


    介绍

    创建系统管理app,用于管理系统的用户,角色,权限,登录等功能,项目中将使用django-rest_framework进行用户认证和权限解析。这里将完成用户认证

    用户验证

    rest_framework.authentication模块中的认证类,例如:
    session认证:SessionAuthentication(基于session)
    token 认证:TokenAuthentication(API Token)
    自定义认证:BasicAuthentication(HTTP Basic Auth)

    1. 这里采用djangorestframework-simplejwt设计自定义认证类和自定义登录
    pip install djangorestframework-simplejwt
    
    • 1
    1. 创建用户模型表user
    from django.db import models from django.contrib.auth.hashers import make_password, check_password
    
    # Create your models here.
    
    class User(models.Model):
        username = models.CharField(max_length=255, unique=True, verbose_name="手机号")
        password = models.CharField(max_length=255, unique=False, verbose_name="密码")
        is_vip = models.BooleanField(default=False,verbose_name="是否为vip")
        vip_expires_at = models.DateTimeField(auto_now_add=True,verbose_name="vip过期时间")
        is_active = models.BooleanField(default=True)
        
        class Meta:
            db_table = "user"
            verbose_name = "用户账号表"
            verbose_name_plural = verbose_name
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    1. 数据库迁移
    python manage.py makemigrations
    python manage.py migrate 
    
    • 1
    • 2
    1. 在根目录下创建utils目录,在utils目录中创建文件Authentication.py和jwt.py
     ## Authentication.py
     from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
    from rest_framework_simplejwt.views import TokenObtainPairView
    from rest_framework import serializers
    from user.models import User
    
    # 自定义认证类
    class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
        """
        自定义登录认证,使用自有用户表
        username、password这两个字段为必传字段因为 DRF 要检查这些字段是否有效
        username_field = 'phone_number'  这是重命名了,username必传字段设置为了phone_number字段必传
        phone_number = serializers.CharField(required=False) # 这个是设置了自定义的字段是否必传
        """
        def validate(self, attrs):
            username = attrs.get("username")
            password = attrs.get("password")
    
            if not username or not password:
                raise serializers.ValidationError("phone_number and password are required")
    
            try:
                user = User.objects.get(username=username, password=password)
            except User.DoesNotExist:
                raise serializers.ValidationError("No user found with this username and password.")
            print(user)
            refresh = self.get_token(user)
            data = {"userId": user.id, "token": str(refresh.access_token), "refresh": str(refresh),
                    'is_vip': user.is_vip}
            return data
    
    class MyTokenObtainPairView(TokenObtainPairView):
        serializer_class = MyTokenObtainPairSerializer
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    ## jwt.py
    from rest_framework_simplejwt.authentication import JWTAuthentication
    from rest_framework_simplejwt.exceptions import InvalidToken, AuthenticationFailed
    from django.utils.translation import gettext_lazy as _
    # 自定义的用户模型
    from user.models import User
    
    
    class MyJWTAuthentication(JWTAuthentication):
        '''
        修改JWT认证类,返回自定义User表对象
        '''
    
        def get_user(self, validated_token):
            try:
                user_id = validated_token['user_id']
            except KeyError:
                raise InvalidToken(_('Token contained no recognizable user identification'))
    
            try:
                user = User.objects.get(**{'id': user_id})
            except User.DoesNotExist:
                raise AuthenticationFailed(_('User not found'), code='user_not_found')
    
            return user
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    1. 在settings.py同级目录下创建drf_settings.py 并引入settings.py 中
    ## drf_settings.py
    REST_FRAMEWORK = {
        'DEFAULT_PERMISSION_CLASSES': [
            'rest_framework.permissions.IsAuthenticated',
        ],
        'DEFAULT_AUTHENTICATION_CLASSES': [
            'utils.jwt.MyJWTAuthentication' # 认证方式为自定义的认证类
        ],
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    引入settings中

    import drf_settings
    REST_FRAMEWORK = drf_settings.REST_FRAMEWORK
    
    • 1
    • 2
    1. 创建一个app:userauth,在views.py中写入一个接口视图
    from django.shortcuts import render
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    # Create your views here.
    
    class UserTestView(APIView):
        def post(self, request,*args, **kwargs):
            s = str(request.user.__dict__)
            return Response(s)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1. 在app:userauth:urls中设置路由
    from django.urls import path, include
    from rest_framework import routers
    from rest_framework_simplejwt.views import TokenVerifyView, TokenRefreshView
    from utils.authentication import MyTokenObtainPairView
    from userauth.views import UserTestView
    
    router = routers.DefaultRouter()
    
    
    urlpatterns = [
        path("login/", MyTokenObtainPairView.as_view()),                           # 登录
        path("refresh/", TokenRefreshView.as_view(), name="token_refresh"),        # 刷新token
        path("verify/", TokenVerifyView.as_view(), name="token_verify"),            # 验证token
        path("test/", UserTestView.as_view(), name="test")
    ]
    urlpatterns.append(path('', include(router.urls)))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    1. 这里没有写注册功能,所以只有手动在数据库中创建一个用户
      在这里插入图片描述

    2. 使用postman进行登录测试
      在这里插入图片描述

    3. 刷新token测试
      在这里插入图片描述

    4. 接口测试
      在这里插入图片描述

    参考链接:https://blog.csdn.net/qq_42410176/article/details/130568130?spm=1001.2014.3001.5502

  • 相关阅读:
    JavaScript从入门到精通|函数
    单片机实验--单片机控制数码管
    LTE 网络与互联网的连接
    别再纠结线程池池大小、线程数量了,哪有什么固定公式 | 京东云技术团队
    Linux CentOS7 vim宏操作
    淘宝代购系统需要电商API接口
    laravel 自定义节流中间件
    aspnetcore插件开发dll热加载 二
    TOPS是每秒一万亿次操作
    【AI设计模式】01-数据表示-特征哈希(Feature Hashed)模式
  • 原文地址:https://blog.csdn.net/weixin_45983953/article/details/136340755