DRF 三大认证

2024-04-23 03:12
文章标签 认证 三大 drf

本文主要是介绍DRF 三大认证,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

三大认证使用

【0】准备

(1)APIView源码回顾

  • APIView不用csrf验证了
  • APIView的request方法不在是以前的request方法,有了很多好用的新方法
  • APIView内部还分别进行了了用户、权限、频率的验证
  • 三大认证之后才执行的视图层的方法

image-20240417144150517

(2)模型表创建

from django.db import models# 图书表
class Book(models.Model):name = models.CharField(max_length=64, verbose_name="书名")price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="价格")publish_name = models.CharField(max_length=64, verbose_name="出版社名字")# 用户表
class User(models.Model):name = models.CharField(max_length=64, verbose_name='用户名')password = models.CharField(max_length=64, verbose_name='密码')role = models.IntegerField(choices=((0, "Admin"), (1, 'Normal')), verbose_name='用户名')# 用户token表
class UserToken(models.Model):token = models.CharField(max_length=64, verbose_name='token')user = models.OneToOneField(to=User, on_delete=models.CASCADE, verbose_name="关联用户表")

【1】认证组件

(1)简介

  • 三大认证之首,只有通过这个认证才会进行两外两个认证
  • 认证组件用于确定请求是来自谁。例如,它可以检查一个请求是否附带了一个有效的用户会话token,从而识别出请求的用户。

(2)使用方法

  1. 编写一个继承BaseAuthentication的类

    • from rest_framework.authentication import BaseAuthentication
  2. 重写authenticate方法

    • 可以在BaseAuthentication类中看到authenticate() must be overridden的提示,提示我们要重写
  3. 重写方法中进行特殊内容的判断(这里是token)

    • token是后端开发者对前端传输数据进行要求的,可以指定内容,可以指定格式,由于无论什么请求方式,都会发送请求头,所以可以指定数据放在请求头中
    • 请求通过,直接返回用户对象和token
    • 请求失败,抛异常AuthenticationFailed
      • from rest_framework.exceptions import AuthenticationFailed
      • 例如:raise AuthenticationFailed("请先登录再重试。")
  4. 配置使用

    1. 局部使用

      • 在试图内中添加authentication_classes = [自定义认证类列表],这是个列表,所以说明可以添加多个认证类
    2. 全局使用

      • 直接去drfsetting配置文件中找

      • REST_FRAMEWORK = {'DEFAULT_AUTHENTICATION_CLASSES': ['字符串形式导入自定义认证类',],
        }
        
    3. 局部禁用

      • 再进行全局配置即所有视图类都需要登录认证以后
      • 根据就近优先原则,只要将当前的视图类中authentication_classes 置空就可以取消认证,即局部禁用

(3)示例

  • 路由层:使用继承ViewSetMixin的视图类,所以直接自动生成路由
from django.urls import path, include
from .views import UserAPIView
from rest_framework.routers import SimpleRouterrouter = SimpleRouter()
router.register(prefix='user', viewset=UserAPIView, basename='user')
router.register(prefix='book', viewset=BookAPIView, basename='book')
urlpatterns = [path('', include(router.urls))
]
  • 视图函数登录功能
    • 注册就直接再数据库添加了
    • update_or_create(defaults={'token': token}, user=user_obj)讲解
      • defaults参数是一个字典,需要添加的所有字段信息(除了后面的那个字段)
      • 这里的字段是user,即根据user进行判断,这个数据是已经添加过的还是新的,如果是新的那么就是创建,如果是旧的数据,那么就进行更新
# 登录功能
import uuid
from rest_framework.viewsets import ViewSet
from .models import User, UserToken
from rest_framework.response import Response
from rest_framework.decorators import actionclass UserAPIView(ViewSet):@action(methods=['post'], detail=False)def login(self, request):username = request.data.get('username')password = request.data.get('password')user_obj = User.objects.filter(username=username, password=password).first()if user_obj:token = uuid.uuid4()UserToken.objects.update_or_create(defaults={'token': token}, user=user_obj)return Response({"code": 100, "msg": "登录成功", "token": token})return Response({"code": 101, "msg": "登录失败,用户名或密码错误"})
# 书籍查询所有,添加单本
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin, CreateModelMixin
from .serializer import BookModelSerializer
from .authentication import LoginAuthclass BookAPIView(GenericViewSet, ListModelMixin, CreateModelMixin):queryset = Book.objects.all()serializer_class = BookModelSerializer# 认证类authentication_classes = [LoginAuth]# 序列化类
from rest_framework.serializers import ModelSerializer
from .models import Bookclass BookModelSerializer(ModelSerializer):class Meta:model = Bookfields = '__all__'
  • 认证类编写
    • 需要注意的是,前端的数据是放在请求头中的token,再后端需要加上HTTP_大写变量取值
    • 最后成功返回usertoken
    • 不成功抛出异常AuthenticationFailed
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from .models import UserTokenclass LoginAuth(BaseAuthentication):def authenticate(self, request):token = request.META.get("HTTP_TOKEN")token_obj = UserToken.objects.filter(token=token).first()if token_obj:return token_obj.user, tokenraise AuthenticationFailed("请先登录再重试。")
  • 试图函数测试:书籍信息查询功能
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from .serializer import BookModelSerializer
from .authentication import LoginAuthclass BookAPIView(GenericViewSet, ListModelMixin):queryset = Book.objects.all()serializer_class = BookModelSerializerauthentication_classes = [LoginAuth]
  • 不登陆测试

image-20240417154617946

  • 登录后添加token测试

image-20240417155235666

【2】权限组件

(1)简介

  • 三大认证的第二个,到这里说明已经通过了认证组件
  • 权限组件用于确定已认证的用户是否有权限执行某个操作。例如,一个API视图可能只允许特定的用户组或具有特定权限的用户访问。

(2)使用方法

  1. 编写一个继承BasePermission的类

    • from rest_framework.permissions import BasePermission
  2. 重写has_permission方法

    • 根据自定义规则,通过返回True,失败返回False
    • 验证不通过自定义返回信息f方法,抛出异常AuthenticationFailed
      • from rest_framework.exceptions import PermissionDenied
      • 例如:raise PermissionDenied(f'你是【{role_info}】,没有权限执行当前操作。')
  3. 配置使用

    1. 局部使用

      • 在试图内中添加permission_classes = [自定义权限类列表],这是个列表,所以说明可以添加多个权限类
    2. 全局使用

      • 直接去drfsetting配置文件中找

      • REST_FRAMEWORK = {'DEFAULT_PERMISSION_CLASSES': ['字符串形式导入自定义认证类',],
        }
        
    3. 局部禁用

      • 再进行全局配置即所有视图类都需权限认证以后
      • 根据就近优先原则,只要将当前的视图类中permission_classes 置空就可以取消权限认证,即局部禁用

(3)示例

  • 注意:前面必须要有认证类通过认证才可以即一定要有authentication_classes,因为这里的权限认证是从登录后的信息拿取权限的内容

  • 权限类编写

    • 根据自定义规则进项权限检查
    • 最后成功返回True
    • 不成功抛出异常PermissionDenied
    • 由于User表是自定义的没有继承django的用户表,所以是没有is_authenticated方法,需要再模型表中自定义,返回个True即可,表示是这个表创建的
# 权限
from rest_framework.permissions import BasePermission
from rest_framework.exceptions import PermissionDeniedclass AdminPermission(BasePermission):def has_permission(self, request, view):# 检查是否登录if request.user.is_authenticated:# 检查权限只有管理员才可以if request.user.role == 0:return Truerole_info = request.user.get_role_display()raise PermissionDenied(f'你是【{role_info}】,没有权限执行当前操作。')raise PermissionDenied(f'请先登录执行当前操作。')# 模型表
class User(models.Model):username = models.CharField(max_length=64, verbose_name='用户名')password = models.CharField(max_length=64, verbose_name='密码')role = models.IntegerField(choices=((0, "Admin"), (1, 'Normal')), verbose_name='用户名')@propertydef is_authenticated(self):return True
  • 视图函数测试:
    • 在添加一个书籍对单本图书的视图函数,使用路由注册视图集时,每个视图集通常应该对应一个特定的 URL 前缀,以避免冲突。
# 路由层
from django.urls import path, include
from .views import UserAPIView, BookAPIView, BookOneAPIView
from rest_framework.routers import SimpleRouterrouter = SimpleRouter()
router.register(prefix='user', viewset=UserAPIView, basename='user')
router.register(prefix='books', viewset=BookAPIView, basename='books')
router.register(prefix='book', viewset=BookOneAPIView, basename='book_one')
urlpatterns = [path('', include(router.urls))
]# 视图层
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, \DestroyModelMixin
from .serializer import BookModelSerializer
from .authentication import LoginAuth
from .permission import AdminPermissionclass BookAPIView(GenericViewSet, ListModelMixin, RetrieveModelMixin):queryset = Book.objects.all()serializer_class = BookModelSerializerauthentication_classes = [LoginAuth]permission_classes = []class BookOneAPIView(GenericViewSet, CreateModelMixin, UpdateModelMixin, DestroyModelMixin):queryset = Book.objects.all()serializer_class = BookModelSerializerauthentication_classes = [LoginAuth]permission_classes = [AdminPermission]
  • 普通用户测试

image-20240417185503126

  • 管理员测试

image-20240417185547653

【3】频率组件

(1)简介

  • 三大认证的最后一个,到这里说明已经通过了认证和权限组件
  • 权限组件用于确定已认证的用户是否有权限执行某个操作。例如,一个API视图可能只允许特定的用户组或具有特定权限的用户访问。

(2)SimpleRateThrottle使用方法

  1. 编写一个继承SimpleRateThrottle的类

    • from rest_framework.throttlingimport SimpleRateThrottle
  2. 重写get_cache_key方法

    • 可以在SimpleRateThrottle类中看到get_cache_key() must be overridden的提示,提示我们要重写
    • 在类属性中定义一个rate属性
      • 参数形式为:3/m,这里表示一分钟内最多访问三次
      • 所以第一个参数是次数,/后面的是单位,s是秒,m是分钟,h是小时,实际上写全称也可以,只和首字母有关,源码导致
    • 这个方法需要返会限制频率的唯一标识
      • 返回request.META.get('REMOTE_ADDR')表示IP
  3. 配置使用

    1. 局部使用

      • 在试图内中添加throttle_classes= [自定频率类列表],这是个列表,所以说明可以添加多个频率类
    2. 全局使用

      • 直接去drfsetting配置文件中找

      • REST_FRAMEWORK = {'DEFAULT_THROTTLE_CLASSES': ['字符串形式导入自定义频率类',],
        }
        
    3. 局部禁用

      • 再进行全局配置即所有视图类都限制频率以后
      • 根据就近优先原则,只要将当前的视图类中throttle_classes 置空就可以取消频率限制,即局部禁用

(3)示例

  • 频率类编写
    • 重写get_cache_key方法,返回IP
    • 添加类属性rate
from rest_framework.throttling import BaseThrottle, SimpleRateThrottleclass CommonThrottle(SimpleRateThrottle):rate = '3/m'def get_cache_key(self, request, view):return request.META.get('REMOTE_ADDR')
  • 视图函数测试:
class BookAPIView(ReadOnlyModelViewSet):queryset = Book.objects.all()serializer_class = BookModelSerializerauthentication_classes = [LoginAuth]permission_classes = []throttle_classes = [CommonThrottle]

image-20240417191537786

(4)BaseThrottle使用方法

  • SimpleRateThrottle的使用方法差不多,不过要麻烦很多,几乎要完全自定义,需要重写allow_request方法

  • 补充一点:

    • 正常来说,通过返回True,不通过返回False
    • 但是不通过可以自定义返回信息,使用Throttled实例化一个信息,并抛出这个异常。
      • from rest_framework.exceptions import Throttled
from rest_framework.throttling import BaseThrottle
from rest_framework.exceptions import Throttledclass ComplexThrottle(BaseThrottle):login_dict = {}  # 登录信息字典frequency = 3  # 时间内访问次数interval = 10  # 时间间隔 sdef allow_request(self, request, view):print(self.login_dict)now_ip = request.META.get('REMOTE_ADDR')now_time = time.time()# 是否是新用户if now_ip not in self.login_dict.keys():self.login_dict[now_ip] = [now_time]return Trueelse:# 时间间隔dif = now_time - self.login_dict.get(now_ip)[0]# 时间间隔大于指定间隔if dif > self.interval:self.login_dict.get(now_ip).pop(0)self.login_dict.get(now_ip).append(now_time)return True# 存储超过指定数量不在添加elif len(self.login_dict.get(now_ip)) >= self.frequency:# 自定义返回内容raise Throttled(detail={'msg': f"访问频率过高,请等待{self.interval - int(dif)}秒后再试。"})# 最后说明:在时间间隔内,且有位置可以添加else:self.login_dict[now_ip].append(now_time)return True

这篇关于DRF 三大认证的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/927625

相关文章

springboot security使用jwt认证方式

《springbootsecurity使用jwt认证方式》:本文主要介绍springbootsecurity使用jwt认证方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录前言代码示例依赖定义mapper定义用户信息的实体beansecurity相关的类提供登录接口测试提供一

SpringSecurity 认证、注销、权限控制功能(注销、记住密码、自定义登入页)

《SpringSecurity认证、注销、权限控制功能(注销、记住密码、自定义登入页)》SpringSecurity是一个强大的Java框架,用于保护应用程序的安全性,它提供了一套全面的安全解决方案... 目录简介认识Spring Security“认证”(Authentication)“授权” (Auth

一文详解kafka开启kerberos认证的完整步骤

《一文详解kafka开启kerberos认证的完整步骤》这篇文章主要为大家详细介绍了kafka开启kerberos认证的完整步骤,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、kerberos安装部署二、准备机器三、Kerberos Server 安装1、配置krb5.con

java如何通过Kerberos认证方式连接hive

《java如何通过Kerberos认证方式连接hive》该文主要介绍了如何在数据源管理功能中适配不同数据源(如MySQL、PostgreSQL和Hive),特别是如何在SpringBoot3框架下通过... 目录Java实现Kerberos认证主要方法依赖示例续期连接hive遇到的问题分析解决方式扩展思考总

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

【Kubernetes】K8s 的安全框架和用户认证

K8s 的安全框架和用户认证 1.Kubernetes 的安全框架1.1 认证:Authentication1.2 鉴权:Authorization1.3 准入控制:Admission Control 2.Kubernetes 的用户认证2.1 Kubernetes 的用户认证方式2.2 配置 Kubernetes 集群使用密码认证 Kubernetes 作为一个分布式的虚拟

【Shiro】Shiro 的学习教程(二)之认证、授权源码分析

目录 1、背景2、相关类图3、解析3.1、加载、解析阶段3.2、认证阶段3.3、授权阶段 1、背景 继上节代码,通过 debug 进行 shiro 源码分析。 2、相关类图 debug 之前,先了解下一些类的结构图: ①:SecurityManager:安全管理器 DefaultSecurityManager: RememberMeManager:实现【记住我】功能

OpenStack离线Train版安装系列—3控制节点-Keystone认证服务组件

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版

OpenStack Victoria版——3.控制节点-Keystone认证服务组件

3.控制节点-Keystone认证服务组件 更多步骤:OpenStack Victoria版安装部署系列教程 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版 离线安装部署系列教程(全) OpenStack Train版 离线安装部署系列教程(全) 欢迎留言沟通,共同进步。 文章目录 创建key

JVM、JRE和 JDK:理解Java开发的三大核心组件

Java是一门跨平台的编程语言,它的成功离不开背后强大的运行环境与开发工具的支持。在Java的生态中,JVM(Java虚拟机)、JRE(Java运行时环境)和JDK(Java开发工具包)是三个至关重要的核心组件。本文将探讨JVM、JDK和JRE的区别,帮助你更好地理解Java的运行机制。 1. JVM:Java虚拟机(Java Virtual Machine) 什么是JVM? JVM,即