token认证

登录的token操作

#app.models.py :表结构
from django.db import models
class User(models.Model):
    user = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    def __str__(self):
        return self.user
class UserToken(models.Model):
    token = models.CharField(max_length=64)
    user = models.OneToOneField(to='User')
    
#app.objectjson.py :序列化模块
from rest_framework import serializers
from app import models
class UserJson(serializers.ModelSerializer):
    class Meta:
        model = models.User
        fields = '__all__'

#app.views.py 
from rest_framework.views import APIView
from rest_framework.response import Response
from app import models, common, objectjson


class Login(APIView):
    def post(self, request):
        data_dic = request.data
        user = models.User.objects.filter(**data_dic).first()
        if user:
            # 登录成功操作token
            token = common.get_token()
            # token的数据库操作,第一次产生token是新建,再次就是更新
            models.UserToken.objects.update_or_create(user=user, defaults={'token': token})
            user_data = objectjson.UserJson(user).data
            return Response({
                'status': 0,
                'message': 'login success',
                'token': token,  # 将token返回给前台
                'results': user_data
            })
        return Response({
            'status': 1,
            'message': 'login failedr'
        })

认证方法的实现

#源码分析
# as_view()=> APIView.dispatch => self.initial(request,*args,**kwargs) => 封装后的drf的request => request.user => self._authenticate() => authenticate(self,reuquest)的源码根据地

#app.views.py
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed


class LoginAuthenticate(BaseAuthentication):
    def authenticate(self, request):
        # 登录逻辑:如果用户登录了,登录操作产生了token,且前后台同步了
        # 登录判断:再次发生请求,没有token代表没登录,错误token,代表无效的登录,token正确才是正常的登录用户
        # 如何将token取出,规定token用请求头传递
        token = request.META.get('HTTP_TOKEN')
        result = models.UserToken.objects.filter(token=token).first()
        print(result)
        if result:
            # 认证通过,可以返回None(有多个认证时),可以返回两个值:user,auth
            return result.user, token
        else:
            # 认证失败,抛出APIException或其子类对象
            raise AuthenticationFailed('认证失败')


class Books(APIView):
    authentication_classes = [LoginAuthenticate]

    # 视图函数处理的逻辑
    def get(self, request):
        # 通过认证后,用request.user拿到当前登录的用户,用request.auth拿到认证值(该值通常自定义)
        print(request.user)
        return Response({
            'status': 0,
            'message': 'ok',
            'results': []
        })

局部认证

#app.auth.py 完成校验的所有逻辑
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app import models
class LoginAuthenticate(BaseAuthentication):
    def authenticate(self, request):
        token = request.META.get('HTTP_TOKEN')
        result = models.UserToken.objects.filter(token=token).first()
        print(result)
        if result:
            return result.user, token
        else:
            raise AuthenticationFailed('认证失败')

class Books(APIView):
  #添加登录认证即可
    authentication_classes = [auth.LoginAuthenticate]
    def get(self, request):
        print(request.user)
        return Response({
            'status': 0,
            'message': 'ok',
            'results': []
        })

全局认证

# 1.在settings.py中配置
# 全局认证
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'app.auth.LoginAuthenticate'
    ),
}
#2.所有的CBV类都不需要添加类属性:authentication_classes
# 局部禁用 
# 3.在不需要认证的CBV类中添加类属性:authentication_classes =[]

注销:在全局认证情况下

class Logout(APIView):
    # 在全局认证情况下,如果能走get方法,代表已经通过登录认证(登录状态),就可以注销
    def get(self, request):
        models.UserToken.objects.update_or_create(user=request.user, defaults={'token': common.get_token()})
        return Response({
            "status": 0,
            "msg": 'logout success',
        })

猜你喜欢

转载自www.cnblogs.com/ShenJunHui6/p/10883372.html