DRF之三大认证

一、认证Authentication

  认证主要用于登录认证,判断用户是否登录。在用户登录时返回一个随机的字符串,之后再访问时通过字符串判断用户是否登录。

  登录接口举例:

    编写步骤:

      创建user表和一对一userToken表,在前端传入用户名密码,在后端接收去user表中对比,对比成功就让他登录。

      登录成功后在userToken表中记录,并返回随机字符串,下次通过比对字符串判断是否登录。

    models:   

复制代码
class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    user_type = models.IntegerField(choices=((1, '超级管理员'), (2, '普通管理员'), (3, '普通用户')))
    # gender=models.IntegerField(choices=((1,"男"),(2,"女"),(0,"未知"))) # 1:男  2:女 0:未知
    # user对象.get_字段名_display()  快速取出gender数字对应的中文


class UserToken(models.Model):
    user = models.OneToOneField(to=User,on_delete=models.CASCADE)
    token = models.CharField(max_length=32)
复制代码

    views:

复制代码
from rest_framework.viewsets import ViewSet
from rest_framework.decorators import action
from .models import User, UserToken
import uuid
from rest_framework.response import Response

# class UserView(ViewSetMixin,APIView):
class UserView(ViewSet):
    @action(methods=['POST'], detail=False)
    def login(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        user = User.objects.filter(username=username, password=password).first()
        if user:
            # 登陆成功--》生成一个随机字符串-->存到token表中(如果之前有记录,更新,如果没有新增)
            # uuid生成不重复的串---》理论上不重复
            token = str(uuid.uuid4())  # 伪随机数生成,没有参数,重复概率,比其他的高一些
            UserToken.objects.update_or_create(user=user, defaults={'token': token})  # 判断user是否存在,如果存在就更新,如果不存在就新增
            return Response({'code': 100, 'msg': '登陆成功', 'token': token})
        else:
            return Response({'code': 101, 'msg': '用户名或密码错误'})
复制代码

  urls:

复制代码
from django.contrib import admin
from django.urls import path, include
from app01 import views
from rest_framework.routers import SimpleRouter

router = SimpleRouter()
router.register('user', views.UserView, 'user')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(router.urls)),
]
复制代码

 

  认证类:

    完成登录接口之后就可编写登录认证了:

    编写步骤:

      写一个类,继承BaseAuthentication,重写authenticate,在方法中做校验,校验是否登录,返回两个值,没有登录抛异常

    新建一个auth.py:

复制代码
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from .models import UserToken


# 编写认证类
# 全局使用,局部使用

# 步骤:写一个类,继承BaseAuthentication,重写authenticate,在方法中做校验,校验是否登录,返回两个值,没有登录抛异常

class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        # 前端带过来的token,放在哪,是接口(我们)固定的
        token = request.query_params.get('token')
        user_token = UserToken.objects.filter(token=token).first()
        if user_token:  # 登录了
            # 第一个:当前登录用户,第二个:token返回
            return user_token.user, token
        else:
            # 抛出认证失败的异常
            raise AuthenticationFailed('您没有登录')
复制代码

    配置认证:

      全局配置方式:

        可以在配置文件中配置全局默认的认证方案

 REST_FRAMEWORK={
      "DEFAULT_AUTHENTICATION_CLASSES":["app01.auth.LoginAuth",]
          }

      局部配置方式:

        在视图类中配置:

class UserView(ViewSet):
        authentication_classes = [LoginAuth] 

      局部禁用:

        在全局配置后在指定的视图类中配置:

 class UserView(ViewSet):
            authentication_classes = [] 

 

二 权限Permissions

  权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。

    • 在执行视图的dispatch()方法前,会先进行视图访问权限的判断
    • 在通过get_object()获取具体对象时,会进行模型对象访问权限的判断

  权限举例:超级用户才能增删改,普通用户只有查单条和多条的权限。

  编写步骤:写一个类,继承BasePermission,重写has_permission,判断如果有权限,返回True,如果没有权限,返回False

  auth:

复制代码
from rest_framework.permissions import BasePermission


class UserPermission(BasePermission):
    def has_permission(self, request, view):
        self.message='您是:%s,没有权限'%request.user.get_user_type_display()  # 没有权限的提示信息
        # 如果有权限,返回True,没有权限返回False
        # 权限类,在认证类之后,request.user有了当前登录用户
        user_type = request.user.user_type
        if user_type < 2:  # 只要不是超级用户,就没有权限
            return True
        else:
            return False
复制代码

 

  将5个接口分在两个视图写:

  views:

复制代码
# 普通用户,只能查看
from .auth import IPThrottle
class BookView(GenericViewSet, ListModelMixin, RetrieveModelMixin):
    authentication_classes = [LoginAuth,]
    queryset = Book.objects.all()
    serializer_class = BookSerializer


# 普通用户以上,才能修改。。。
from .auth import UserPermission

class BookDetailView(GenericViewSet, CreateModelMixin, DestroyModelMixin, UpdateModelMixin):
    authentication_classes = [LoginAuth, ]
    permission_classes = [UserPermission, ]
    queryset = Book.objects.all()
    serializer_class = BookSerializer
复制代码

 

  使用方式:

    全局使用:

      可以在配置文件中配置全局默认的认证方案

REST_FRAMEWORK={
            "DEFAULT_PERMISSION_CLASSES":["app01.auth.UserPermission",]
        }

 

    局部使用:

      在视图函数中配置:

class BookDetailView(GenericViewSet, CreateModelMixin, DestroyModelMixin, UpdateModelMixin):
    permission_classes = [UserPermission, ]

 

三、频率

  可以对接口访问的频次进行限制,以减轻服务器压力。

  使用方式:写一个类,继承SimpleRateThrottle,重写类属性:scope,和get_cache_key方法

    get_cache_key返回什么,就以什么做限制,scope配置文件中要用

  auth:

复制代码
# 频率限制类
from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
class IPThrottle(SimpleRateThrottle):
    scope = 'minute_3'  # 随便写
    # 返回什么,就以什么做现在
    def get_cache_key(self, request, view):
        # 限制ip地址---》request.META字典---》请求头中数据
        return request.META.get('REMOTE_ADDR') # 客户端ip
        # return request.user.id # 用户id限制


class UserThrottle(SimpleRateThrottle):
    scope = 'minute_5'  # 随便写
    # 返回什么,就以什么做现在
    def get_cache_key(self, request, view):
        return request.user.id
复制代码

  在配置文件中配置:

       'DEFAULT_THROTTLE_RATES': {
        'minute_3': '3/m'  # minute_3是scope的字符串,一分钟访问3次
        'minute_5''5/m'
    }

  局部使用:

    在视图类中配置:

    

  class BookView(GenericViewSet, ListModelMixin, RetrieveModelMixin):
    throttle_classes = [IPThrottle]

  全局使用:

    在配置文件中配置:

 'DEFAULT_THROTTLE_CLASSES': (  # 全局配置频率类
        'app01.auth.IPThrottle'
    ),
  

 

posted @   临江沂水  阅读(88)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示