drf之基于自定义表签发token及基于自定义表编写认证类

发布时间 2024-01-06 19:38:45作者: jntmwl

基于自定义表签发token

1 快速签发和认证

2 定制返回格式和认证

3 自定义登录和认证

4 自定义登录,自定义表

5 自定义认证类

url.py

from django.contrib import admin
from django.urls import path
from rest_framework.routers import SimpleRouter
from .views import UserView

router = SimpleRouter()
router.register('user', UserView, 'user')
urlpatterns = [

]
urlpatterns += router.urls

view.py

from rest_framework.decorators import action
from rest_framework.viewsets import GenericViewSet
from rest_framework.response import Response
from .serializer import LoginSerializer

class UserView(GenericViewSet):
serializer_class = LoginSerializer

# 127.0.0.1:8000/api/v1/user/login/
@action(methods=['POST'], detail=False)
def login(self, request):
    ser = self.get_serializer(data=request.data)
    ser.is_valid(raise_exception=True)
    return Response(ser.validated_data)

序列化类

from rest_framework import serializers
from .models import UserInfo
from rest_framework.exceptions import APIException
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer, TokenObtainSerializer


# 只做校验
class LoginSerializer(serializers.Serializer):
    username = serializers.CharField()
    password = serializers.CharField()

    def validate(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        user = UserInfo.objects.filter(username=username, password=password).first()
        if user:
            # 签发token,使用RefreshToken直接签发
            refresh = RefreshToken.for_user(user)
            return {
                'code': 100,
                'msg': '登录成功',
                'username': username,
                # 'icon':user.icon,
                'access': str(refresh.access_token),
                'refresh': str(refresh)

            }
        else:
            raise APIException({'code': 999, 'msg': '用户名或密码错误11'})

表模型

class UserInfo(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    age = models.IntegerField()
    gender = models.IntegerField(choices=((1, '男'), (2, '女'), (0, '未知')))

基于自定义表编写认证类

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import APIException
from rest_framework_simplejwt.tokens import AccessToken

from rest_framework_simplejwt.authentication import JWTAuthentication

# JWTAuthentication 有authenticate 里面完成对token的认证

from .models import UserInfo


class LoginAuthentication(BaseAuthentication):
    def authenticate(self, request):
        # 1 取出前端传入的token:它放哪了?后端定的:定死key值叫token:value值直接不带任何前缀
        token = request.META.get('HTTP_TOKEN')
        if token:
            # validated_token = self.get_validated_token(token)---》返回了AccessToken(token)传入的对象
            # 2 拿到token,验证token是否合法,是否过期,是否被篡改,伪造,如果都通过,根据payload中得userid取出当前用户
            try:
                validated_token = AccessToken(token)  # 源码中拿出来的
            except Exception as e:
                raise APIException({'code': 888, 'msg': str(e)})
            # 3 取出用户id,根据用户id,查出用户,返回
            # validated_token.payload['user_id']
            # validated_token['user_id']
            user = UserInfo.objects.filter(pk=validated_token['user_id']).first()
            return user, token

        else:
            raise APIException({'code': 101, 'msg': 'token必须携带'})