自定义表签发token与自定义表编写认证类
自定义表签发token
不通过auth_user表,而是通过自定义表实现签发token
代码如下:
表模型:
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, '未知')))
插入数据:
自定义路由层(路由分发):
app下新建urls文件:
from django.contrib import admin from django.urls import path from rest_framework.routers import SimpleRouter from .views import UserView,BookView router = SimpleRouter() router.register('user', UserView, 'user') urlpatterns = [ ] urlpatterns += router.urls
序列化类:
新建serializer.py文件
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': '用户名或密码错误'})
视图层:
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)
实现效果如下:
自定义表编写认证类
自定义用户表使用JWTAuthentication无法完成验证,必须自定义认证类
代码如下:
自定义认证类
新建auth.py文件
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 from rest_framework_simplejwt.serializers import TokenRefreshSerializer 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必须携带'})
视图层
from rest_framework_simplejwt.authentication import JWTAuthentication from rest_framework.permissions import IsAuthenticated from .auth import LoginAuthentication class BookView(GenericViewSet): # 自定义用户表,使用JWTAuthentication无法完成验证,必须自定义认证类 # authentication_classes = [JWTAuthentication] # permission_classes = [IsAuthenticated] # 自定义用户表,使用自定义认证类 authentication_classes = [LoginAuthentication] def list(self, request): print(request.user.username) return Response('数据')
路由
# 注册路由即可 router.register('books', BookView, 'books')
实现效果如下: