首页 > 其他分享 >drf之三大组件(认证组件、权限组件、频率组件)

drf之三大组件(认证组件、权限组件、频率组件)

时间:2023-04-26 18:23:32浏览次数:33  
标签:models 之三 认证 token 组件 import 类中 drf

目录

环境准备

创建相关的表,models.py

class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)


class auth(models.Model):
    token = models.CharField(max_length=64, unique=True)
    user = models.OneToOneField(to='User', on_delete=models.CASCADE, null=True)

创建登录样例

需求:当用户登录后,自动生成一个token随机字符串,并写入到数据库中。

需要使用两个新功能:

  • import uuid 可以生成一个随机字符串
  • orm的update_or_create
    • update_or_create作用是在数据库中执行更新或插入操作。它可以根据给定的筛选条件来查找一条记录,如果找到则更新该记录,否则插入一条新记录。
    • 其中,defaults 参数用于指定需要更新或插入的数据,它是一个字典类型;**kwargs 参数用于指定查找记录所需要的筛选条件,通常是字段名和字段值的键值对形式。
    • 需要注意的是,如果要使用 update_or_create 方法,必须定义一个唯一索引或唯一约束来确保更新或插入的数据不会与现有数据冲突。否则在插入时会抛出唯一性冲突的异常。
from app01 import models
from app01.serializer.serializer import BookModelSerializer
from rest_framework.viewsets import ModelViewSet, ViewSet
from rest_framework.response import Response
from rest_framework.decorators import action
class UserView(ViewSet):
    @action(methods=['POST'], detail=False)
    def login(self, request):
        username = request.POST.get('username')
        password = request.POST.get('password')
        user_obj = models.User.objects.filter(username=username, password=password).first()
        if user_obj:
            print('登录成功')
            # 如果登录成功,则生成一个随机字符串-uuid
            import uuid
            # 生成一个“永不重复”的随机字符串
            token = str(uuid.uuid4())
            # update_or_create作用是在数据库中执行更新或插入操作。它可以根据给定的筛选条件来查找一条记录,如果找到则更新该记录,否则插入一条新记录。
            # 其中,defaults 参数用于指定需要更新或插入的数据,它是一个字典类型;**kwargs 参数用于指定查找记录所需要的筛选条件,通常是字段名和字段值的键值对形式。
            # 需要注意的是,如果要使用 update_or_create 方法,必须定义一个唯一索引或唯一约束来确保更新或插入的数据不会与现有数据冲突。否则在插入时会抛出唯一性冲突的异常。
            models.Auth.objects.update_or_create(user=user_obj, defaults={'token': token})
            return Response({'code': 100, 'msg': '恭喜!!登录成功!'})
        else:
            print('用户名或密码错误')
            return Response({'code': 101, 'msg': '登录失败,用户名或密码错误'})

配置路由

from rest_framework.routers import SimpleRouter
login_route = SimpleRouter()
login_route.register('', views.UserView, '')
urlpatterns = [
    path('', include(login_route.urls))
]

认证组件BaseAuthentication

需求:添加登录限制,写一个接口,当用户登录后就可以访问,未登录则不能访问。

创建认证组件

  • 新建一个认证用py文件,名字随意,我这里叫permission.py
  • 在permission.py中创建认证类
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app01 import models
class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        # 在这里写认证逻辑,如果是登录过的,则可以访问,否则报错
        # 判断请求中是否有token,判断是否登录
        token = request.META.get('HTTP_AUTHORIZATION', None)
        # 判断前端是否传入了token
        if token:
            # 前端传入了token后,则去数据库中查询是否存在
            user_token = models.Auth.objects.filter(token=token).first()
            if user_token:
                # 正常需要返回两个值,[当前登录用户,token]
                return user_token.user, token
            else:
                raise AuthenticationFailed('用户认证失败')
        else:
            raise AuthenticationFailed('用户未登录,请先登录')

创建测试样例

  1. 用户登录后才可以查询所有
  2. 用户未登录只能按主键查询
from app01 import models
from app01.serializer.serializer import BookModelSerializer
from rest_framework.viewsets import ViewSet, ViewSetMixin
from rest_framework.generics import RetrieveAPIView, ListAPIView
from rest_framework.response import Response
from app01.permission import LoginAuth  # 这个是自己创建的认证类


class BookView(ViewSetMixin, ListAPIView):
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer
	# 在视图中使用认证类
    authentication_classes = [LoginAuth]


class BookDetailView(ViewSetMixin, RetrieveAPIView):
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer

验证如下图,在未使用token和使用错误token时都会报错,输入了正确的token后,可以正常访问数据。
image

总结

1. 创建认证组件

- 新建一个认证用py文件,名字随意,我这里叫permission.py
- 在permission.py中创建认证类,继承BaseAuthentication类并重写authenticate方法
	- 在permission的认证类中,如果认证成功需要返回None或两个值,第一个是登录的用户,第二个是token
	- 在permission的认证类中,如果认证不通过,使用AuthenticationFailed抛异常

2. 局部使用(只在一个视图类中使用,使用后会影响当前视图类中管理的所有接口)

- 导入自己写的认证类
- 在视图类中使用authentication_classes = [LoginAuth]进行调用

3. 全局使用(对所有接口都生效)

- 一般与局部禁用搭配使用,因为登录接口不应该认证
- 配置方法
# 这个配置可以在drf的settings.py中找到(C:\app\Python38\Lib\site-packages\rest_framework\settings.py)
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'app01.permission.LoginAuth'
    ],
}

4. 局部禁用

- 当配置了全局使用后,需要在一个视图类中禁用,禁用方法只要把authentication_classes = [] 定义为空值即可
class BookView(ViewSetMixin, ListAPIView):
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer
    # 局部禁用,只要把下面的配置配置为空值即可
    authentication_classes = []

权限组件BasePermission

需求:实现定义三种用户:超级用户、普通用户、非法用户等

环境准备

在上面的环境的基础上,将用户表添加一个控制用户类型的字段,如下:

class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    user_type = models.IntegerField(choices=((1, '超级管理员'), (2, '普通用户'), (3, '非法用户')), default=2)

权限组件

  1. 创建控制权限类的py文件,文件名自定义
  2. 在文件中定义控制权限类
  3. 在权限类中重写has_permission(self, request, view)方法,实现权限控制
  4. 如果有权限return True,如果没有权限return False

创建权限组件

from rest_framework.permissions import BasePermission
class CustomPermission(BasePermission):
    def has_permission(self, request, view):
        if request.user.user_type == 1:
            # 通过get_user_type_display()方法可获取到choice对应的中文
            self.message = '欢迎%s' % request.user.get_user_type_display()
            return True
        else:
            # 通过get_user_type_display()方法可获取到choice对应的中文
            self.message = '您是%s,无法访问' % request.user.get_user_type_display()
            return False

创建测试样例

from app01 import models
from app01.serializer.serializer import BookModelSerializer
from rest_framework.viewsets import ViewSet, ViewSetMixin
from rest_framework.generics import RetrieveAPIView, ListAPIView
from rest_framework.response import Response
from app01.permission import LoginAuth, CustomPermission


class BookView(ViewSetMixin, ListAPIView):
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer
    authentication_classes = [LoginAuth]
    # 使用permission_classes来开启权限认证
    permission_classes = [CustomPermission]

class BookDetailView(ViewSetMixin, RetrieveAPIView):
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer

总结

  • 当用户使用token登录后,可以使用request.user拿到用户信息
  • get_user_type_display()方法可获取到choice对应的中文

1. 创建认证组件

- 在文件中定义控制权限类
- 在权限类中重写has_permission(self, request, view)方法,实现权限控制
- 如果有权限return True,如果没有权限return False

2. 局部使用(只在一个视图类中使用,使用后会影响当前视图类中管理的所有接口)

- 导入自己写的认证类
- 在视图类中使用permission_classes = [自定义的权限组件]进行调用

3. 全局使用(对所有接口都生效)

- 一般与局部禁用搭配使用,因为登录接口不应该认证
- 配置方法
# 这个配置可以在drf的settings.py中找到(C:\app\Python38\Lib\site-packages\rest_framework\settings.py)
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'app01.permission.CustomPermission',
    ],
}

4. 局部禁用

- 当配置了全局使用后,需要在一个视图类中禁用,禁用方法只要把authentication_classes = [] 定义为空值即可
class BookView(ViewSetMixin, ListAPIView):
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer
    # 局部禁用,只要把下面的配置配置为空值即可
    permission_classes = []

频率组件throttling

  • 频率组件可以控制用户的访问频率,比如每分钟可以发起多少次请求
  • 可以按IP或者用户ID进行频率访问控制
    • 获取用户的IP:request.META.get('REMOTE_ADDR')
    • 获取用户的ID:request.user.pk

创建认证组件

  • 重写get_cache_key(self, request, view)方法
  • 定义scope变量,配置认证组件时使用
  1. 创建认证组件
class CustomThrottle(SimpleRateThrottle):
    scope = 'mythrottle'

    def get_cache_key(self, request, view):
        return request.META.get('REMOTE_ADDR')
  1. 在settings.py中注册
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES': {
        'mythrottle': '5/m',    # 这里是scope定义的名字,5/m是每分钟允许访问5次
    },
}

创建测试样例

from app01 import models
from app01.serializer.serializer import BookModelSerializer
from rest_framework.viewsets import ViewSet, ViewSetMixin
from rest_framework.generics import RetrieveAPIView, ListAPIView
from rest_framework.response import Response
from app01.permission import LoginAuth, CustomPermission
# 导入创建的频率限制类
from app01.throttling import CustomThrottle


class BookView(ViewSetMixin, ListAPIView):
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer
    authentication_classes = [LoginAuth]
    permission_classes = [CustomPermission]
    # 导入相关规则
    throttle_classes = [CustomThrottle]

总结

  • 可以使用request.META.get('REMOTE_ADDR')拿到用户IP信息

1. 创建频率类

- 继承SimpleRateThrottle
- 配置一个类属性:scope = '注册名'
- 在权限类中重写get_cache_key(self, request, view)方法,实现权限控制
- 在settings.py中的REST_FRAMEWORK中进行注册,注册名由scope定义
- 如果需要定制返回错误信息,self.message = '错误信息'  即可

2. 局部使用(只在一个视图类中使用,使用后会影响当前视图类中管理的所有接口)

- 导入自己写的认证类
- 在视图类中使用 throttle_classes = [自定义的权限组件]

3. 全局使用(对所有接口都生效)

- 一般与局部禁用搭配使用,因为登录接口不应该认证
- 配置方法
REST_FRAMEWORK = {
    # 注册
    'DEFAULT_THROTTLE_RATES': {
        'mythrottle': '5/m',    # 这里是scope定义的名字
    },
    # 全局使用
    'DEFAULT_THROTTLE_CLASSES': ['app01.throttling.CustomThrottle'],
}
> ### 局部禁用
	- 当配置了全局使用后,需要在一个视图类中禁用,禁用方法只要把 throttle_classes = [] 定义为空值即可
```python
class BookView(ViewSetMixin, ListAPIView):
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer
    # 局部禁用,只要把下面的配置配置为空值即可
    throttle_classes = []

标签:models,之三,认证,token,组件,import,类中,drf
From: https://www.cnblogs.com/smyz/p/17354831.html

相关文章

  • react18中antd的select选择器组件自定义下拉框的内容
    效果如图导入组件和图标import{Select}from'antd'import{ManOutlined,WomanOutlined}from'@ant-design/icons';const{Option}=Select;数据letuserListOption=[{value:1,label:"小明",avatar:"http://xxx......
  • 17.分类组件Category 动态获取数据
    我们接下来做分类组件Category,这个主要用来管理商品的分类,有一级和二级,可以实现一级与二级之间跳转/pages/category/category.jsx文件内容如下:importReact,{Component}from'react'import{Button,Card,Table,message}from'antd'import{PlusOutlined,......
  • 超大文件上传和断点续传的组件
    ​ 以ASP.NETCoreWebAPI 作后端 API ,用 Vue 构建前端页面,用 Axios 从前端访问后端 API,包括文件的上传和下载。 准备文件上传的API #region 文件上传  可以带参数        [HttpPost("upload")]        publicJsonResultuploadProject(I......
  • Python爬虫基础之三
    Python爬虫基础包括HTTP协议、HTML、CSS和JavaScript语言基础、requests库的使用、BeautifulSoup库的使用、xpath和正则表达式的使用等。此外,还应该了解反爬虫机制和爬虫的一些常见问题及解决方法。上一篇文章讲解了有关条件判断语句、循环语句、元组、字典等相关知识,本节将围绕......
  • 动力节点老杜Vue框架教程【三】Vue组件化
    Vue.js是一个渐进式MVVM框架,目前被广泛使用,也成为前端中最火爆的框架Vue可以按照实际需要逐步进阶使用更多特性,也是前端的必备技能动力节点老杜的Vue2+3全家桶教程已经上线咯!学习地址:https://www.bilibili.com/video/BV17h41137i4/视频将从Vue2开始讲解,一步一个案例,知识点......
  • 动力节点老杜Vue框架教程【三】Vue组件化
    Vue.js是一个渐进式MVVM框架,目前被广泛使用,也成为前端中最火爆的框架Vue可以按照实际需要逐步进阶使用更多特性,也是前端的必备技能动力节点老杜的Vue2+3全家桶教程已经上线咯!学习地址:https://www.bilibili.com/video/BV17h41137i4/视频将从Vue2开始讲解,一步一个案例,知识点由浅入......
  • 排序三角组件
    效果排序三角组件<template><divclass="order"><divclass="order-text"@click="textBtnFn"><slot></slot></div><divclass="order-icon"@click="nabFn"&......
  • 老杜2023最新Vue实战精讲(三)Vue组件化
    动力节点老杜全新版Vue教程笔记分享给大家学习の地止:https://www.bilibili.com/video/BV17h41137i4视频教程从Vue2开始讲解,一步一个案例,知识点由浅入深,然后很自然的过度到Vue3版本。Vue3是目前企业中使用最多的一个版本。视频中会把每一个Vue的知识点讲解的非常通透,不但举例......
  • 深度相机技术之三:原理揭秘之-双目立体视觉
    为什么非得用双目相机才能得到深度?双目立体视觉深度相机的工作流程双目立体视觉深度相机详细工作原理    理想双目相机成像模型    极线约束    图像矫正技术    基于滑动窗口的图像匹配    基于能量优化的图像匹配双目立体视觉深度相机的优缺点--------------......
  • 【HarmonyOS】自定义组件之JavaUI实现通用标题栏组件
    【关键字】标题栏、常用内置组件整合、JavaUI、自定义组件 【1、写在前面】平时我们在开发一个应用时,我们都知道一个完整的项目中会有很多个页面,而这些页面中会有许多通用的部分,比如通用标题栏、通用Dialog、通用下拉菜单等等,在Android开发中我们可以通过LayoutInflater.from......