drf 认证、权限、频率三组件

发布时间 2023-09-06 20:18:50作者: 凡人半睁眼

一、认证组件

1、需求:

通过认证组件去认证,没有认证通过的用户不让登录。认证方式前端发来的token值与数据库进行对比

2、models

from django.db import models

class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    # 用户类型
    user_type = models.IntegerField(choices=((1, '2B用户'), (2, '普通用户'), (3, '超级用户')))

# 一对一的关系
class UserToken(models.Model):
    token = models.CharField(max_length=64)
    # OneToOneField本质就是ForeignKey+unique
    user = models.OneToOneField(to=User, on_delete=models.CASCADE)
    # user = models.ForeignKey(to=User, unique=True,on_delete=models.CASCADE)

2、写一个认证 auth.py

from .models import UserToken
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed

class LoginAuth(BaseAuthentication):
    # 重写一下authenticate方法
    def authenticate(self, request):
        token = request.query_params.get('token')  # 从url中的参数去拿
        print(token) #4d1455f4-97be-4cf6-88a1-dee6e21433ad

        user_token = UserToken.objects.filter(token=token).first()
        if user_token:
            return user_token.user, token
        else:
            raise AuthenticationFailed('您没有登录!')

3、views

class UserView(ViewSet):
    # authentication_classes = []  # 局部解除认证禁用,token没有认证通过就不让登录
    permission_classes = []   # 局部解除权限禁用

    @action(methods=['POST'], detail=False)  # /user/login/    post 请求就会执行
    def login(self, request, *args, **kwargs):
        # 前端传入用户名密码
        username = request.data.get('username')
        password = request.data.get('password')
        user = User.objects.filter(username=username, password=password).first()
        print(user)

        if user:
            # 生成一个随机字符串,返回给前端,并且要把随机字符串存到token表中
            token = str(uuid.uuid4())
            ##### 方式一:麻烦方式
            # user_token=UserToken.objects.filter(user=user).first()
            # if user_token:
            #     user_token.token=token
            #     user_token.save()
            # else:
            #     UserToken.objects.create(user=user,token=token)

            ## 方式二:通过user去UserToken表中查,如果能查到用defaults的更新,如果查不到,就用user和defaults新增一条记录
            # 每次登录会返回一个uuid,会更新uuid
            UserToken.objects.update_or_create(defaults={'token': token}, user=user)
            return Response({'code': 100, 'msg': '登录成功', 'token': token, 'username': user.username})

        else:
            return Response({'code': 101, 'msg': '用户名或密码错误'})

补充:

1、继承 ViewSetMixin,APIView,常见的5个路由自动匹配,其他的通过action装饰器进行指定

4、开启认证

在全局开启认证时需要指定app01下面的auth认证模块

## 全局开启
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'app01.auth.LoginAuth'
    ],
}

##局部开启
authentication_classes = [BasicAuthentication]

##局部禁用
authentication_classes = [] 

5、拿着数据库的token访问

127.0.0.1:8000/user/login/?token=730c7ebf-4b12-4f55-a337-0b341d333395

二、权限组件

1、

2、

3、

三、频率组件

1、

2、

3、