首页 > 其他分享 >DRF之三大认证【认证 权限 频率】

DRF之三大认证【认证 权限 频率】

时间:2024-04-25 20:46:33浏览次数:22  
标签:return ip 之三 request 认证 token user self DRF

DRF之三大认证

【一】三大认证执行顺序

image-20240425162920259

image-20240425163033266

【二】认证

# 我们如果想要自定义认证类,都需要继承 【BaseAuthentication】
from rest_framework.authentication import BaseAuthentication

【1】源码

image-20240425170849844

image-20240425171850793

【2】认证类的使用

###############################  authentications.py ###########
# 导入继承的认证类
from rest_framework.authentication import BaseAuthentication
# 导入认证失败的错误
from rest_framework.exceptions import AuthenticationFailed


class UserAuthenticate(BaseAuthentication):
    # 重写【authenticate】方法
    def authenticate(self, request):
        '''
        进行登录的判断,比如是否携带了token,或是否携带了证明身份信息的东西
        '''
        # 对token 进行校验
        if 'token校验失败':
            # 如果校验失败可以抛出 AuthenticationFailed 异常
            raise AuthenticationFailed('请检查token')
        # 校验通过 返回当前登录用户对象和token
        return user, token
  • 局部使用和全局使用
    • 可以通过authentication_classes = []实现局部禁用
    • 查找验证类的顺序为,先查找类属性中的,再查找项目配置中的,最后去drf默认配置中查找
########### views.py ###########

class 视图类(ViewSet):
    # 局部使用 : authentication_classes = []
    authentication_classes = ['认证类']

########### settings.py ###########

# 全局使用
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # 认证校验
        # 'app001.authenticate.UserAuthenticate'
    ],
}

【3】实例

#### views.py ####
# 在登录时,签发token

class UserViewV2(ViewSetMixin, ListCreateAPIView):
    queryset = UserInfo.objects.all()
    authentication_classes = []

    @action(methods=['POST'], detail=False)
    def login(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        # 进行用户名和密码校验
        user_obj = auth.authenticate(username=username, password=password)
        if not user_obj:
            return Response({'code': 101, 'msg': '登录失败!用户名或密码错误'})
        user_token = uuid.uuid4()
        # 校验成功签发token
        UserToken.objects.update_or_create(defaults={'token': user_token}, user=user_obj)
        return Response({'code': 100, 'msg': '登录成功!', 'token': user_token})
    
    
################# 需要登录才能进入的视图类 #########################
class UserEditViewV2(ViewSetMixin, RetrieveUpdateDestroyAPIView):
    queryset = UserInfo.objects.all()
    serializer_class = UpdatePasswordSerializerV2
    # 局部使用:指定类属性 【authentication_classes】
    authentication_classes = [UserAuthenticate]

    @action(methods=['PUT'], detail=False)
    def password(self, request, *args, **kwargs):
        ser = self.get_serializer(instance=request.user, data=request.data)
        ser.is_valid(raise_exception=True)
        ser.save()
        return Response({'code': 100, 'msg': '修改成功'})
################ authentications.py ###################
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from .models import UserToken


# 继承 【BaseAuthentication】
class UserAuthenticate(BaseAuthentication):
    # 重写 【authenticate】方法
    def authenticate(self, request):
        token = request.META.get('HTTP_TOKEN')
        user_token_obj = UserToken.objects.filter(token=token).first()
        if not user_token_obj:
            raise AuthenticationFailed('请检查token')
        user = user_token_obj.user
        return user, token

【三】权限

# 我们如果想要自定义权限类,都需要继承 【BaseAuthentication】
from rest_framework.permissions import BasePermission

【1】源码

image-20240425185112188

【2】权限类的使用

############### permissions.py ###########
class CommonPermission(BasePermission):
    def has_permission(self, request, view):
        '''
        :param request: 当前请求request对象
        :param view: 视图类
        :return: 布尔值
        '''
        # 可以通过【request.user】中获取到当前登录用户的登录信息
        ### 因为用户需要先通过认证类后才执行权限校验
        # 可以通过【view.basename】获取到视图类的basename属性
        self.message = '可以指定提示信息'
        self.code = '可以指定返回的响应码'
        return True  # 表示权限通过  # 可以访问
    	return False # 表示权限不允许  # 不可以访问
  • 局部使用和全局使用
    • 可以通过permission_classes= []实现局部禁用
########### views.py ###########

class 视图类(ViewSet):
    authentication_classes = ['认证类']
    permission_classes = ['权限类']

########### settings.py ###########

# 全局使用
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # 认证校验
        'app001.authenticate.UserAuthenticate'
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        # 权限校验
        'app001.permissions.CommonPermission'
    ],
}

【3】实例

################ permissions.py #################
# 根据用户表中的is_superuser字段进行权限校验
class CommonPermission(BasePermission):
    def has_permission(self, request, view):
        user = request.user
        # 管理员 都可以操作
        if user.is_superuser:
            return True
        else:
            # 普通用户可以查看或删除车型
            if view.basename == 'car_model' and request.method == 'DELETE':
                return True
            elif request.method != 'GET':
                return False
            else:
                return True

【四】频率

# 我们如果想要自定义频率类,都需要继承 【BaseThrottle】
from rest_framework.throttling import BaseThrottle
# 或者继承已经封装完毕的 【SimpleRateThrottle】
from rest_framework.throttling import SimpleRateThrottle

【1】源码

image-20240425192614719

【2】频率类的使用(SimpleRateThrottle)

class CommonThrottle(SimpleRateThrottle):
    # 重写类属性 【rate】
    rate = '5/m'  # '次数/每多少秒'  # 's': 1, 'm': 60, 'h': 3600, 'd': 86400

    # 重写 【get_cache_key】方法
    def get_cache_key(self, request, view):
        return '返回唯一用户访问的唯一标识  如ip,设备id号'

【2.1】SimpleRateThrottle 实例

############### throttle.py #############
class CommonThrottle(SimpleRateThrottle):
    rate = '5/d'  # 意味着 同一天 同一个ip  只可以访问5次

    def get_cache_key(self, request, view):
        return request.META.get("REMOTE_ADDR")

【2.2】SimpleRateThrottle 源码分析

image-20240425203425526

【3】继承BaseThrottle自定义频率类

  • 重写频率类的,最关键方法就是allow_request方法,在其中构建限制逻辑即可
  • 直接上实例,该实例大部分参考SimpleRateThrottle

不必为仿照而瞧不起自己,读得懂源码,理清楚其中的逻辑也能帮我们很多

#################### throttle.py ############
from rest_framework.throttling import BaseThrottle


class ExtendsThrottle(BaseThrottle):
    # rate = None  # 速率  # 次数/时间
    rate = '3/m'  # 速率  # 次数/时间
    history = {}

    def __init__(self):
        self.count, self.duration = self.parse_rate(self.rate)

    def parse_rate(self, rate: str):
        '''
        将【'3/s'】解析成 次数和持续时间
        :param rate: '3/m'  每分钟限制访问3此
        :return: (次数,持续时间)
        '''
        if not rate:
            return None, None
        time_dict = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}
        count, duration = rate.split('/')
        return int(count), time_dict[duration]

    def get_ident(self, request):
        # 继承父类的获取ip或xff的函数
        # 可以不写,但是为了方便自己理解
        return super().get_ident(request)

    def allow_request(self, request, view):
        '''
        允许访问的主要逻辑代码
        :return: 执行允许通过或不允许通过的方法
        '''
        if not self.rate:
            # 如果不填,就不做限制
            return True
        ip = self.get_ident(request)
        if ip not in self.history:
            # 如果没有来过,初始化历史纪录
            self.history[ip] = []
        ip_history = self.history.get(ip)
        # 添加访问的时间戳
        now = time.time()
        # 当访问次数没达到规定的次数时,不做处理
        while len(ip_history) == self.count:
            # print(now - ip_history[0])
            # 如果这一次请求据第一次请求时间小于规定的时间,限制频率
            if now - ip_history[0] < self.duration:
                return False
            else:
                # 如果举例第一次请求时间大于规定时间,那么允许访问
                # 将第一个请求删除,并在列表最后添加当次的时间戳
                ip_history.pop(0)
                break
        # 将当次的时间戳添加并保存
        ip_history.append(now)
        self.history[ip] = ip_history
        # json.dump(self.history, open('app002/history.json', 'w', encoding='utf-8'))
        return True

标签:return,ip,之三,request,认证,token,user,self,DRF
From: https://www.cnblogs.com/Lea4ning/p/18158526

相关文章

  • 网络实名认证?企业如何实现实名认证?C++身份证实名认证接口
    身份证,大家都不陌生,现如今,我们用到身份证的地方越来越多,人们在办理很多业务时都会要求实名制,比如,电信实名制,火车票,汽车票实名制。为规范网络环境,前段时间国家也出台了相关政策,上网也需要网络实名制,就连大家常用的共享单车在注册时都会要求你实名制,那么,身份证是真是假,是如何确......
  • C++二要素认证,游戏实名认证接口、金融实名认证
    随着移动互联的发展,越来越多的企业在金融市场都想分一杯羹,而哪种理财产品才是人们放心的理财产品呢?我们都知道理财产品开户都需要上传身份证号核验和图像进行验证,以保证个人信息的真实性,那么这些是如何来判别身份证的真伪呢?加入上传一张假的身份证是否也能验证通过呢?翔云身份......
  • DRF之路由组件
    五】路由组件资源路由允许你快速声明给定的有足够控制器的所有公共路由。而不是为你的index...声明单独的路由,一个强大的路由能在一行代码中声明它们。—RubyonRails文档【1】使用SimpleRouter快速生成路由from.viewsimportTaskViewV3#导入模块fromrest_framewor......
  • SpringBoot项目添加2FA双因素身份认证
    什么是2FA(双因素身份验证)?双因素身份验证(2FA)是一种安全系统,要求用户提供两种不同的身份验证方式才能访问某个系统或服务。国内普遍做短信验证码这种的用的比较少,不过在国外的网站中使用双因素身份验证的还是很多的。用户通过使用验证器扫描二维码,就能在app上获取登录的动态口令,......
  • DRF之jwt介绍与使用
    一、jwt介绍1、什么是jwtJWT(JSONWebToken)是一种用于在网络应用中传递信息的开放标准(RFC7519)。它通过在用户和服务器之间传递的信息生成具有一定结构的令牌,这些令牌可以袐用于身份验证和信息传递。它是一种前后端登陆认证的方案,区别于之前的cookie,session。2、JWT结构一个J......
  • DRF之全局异常处理、接口文档书写
    一、全局异常处理1、drf默认异常处理源码分析在DRF中,继承APIView后,它的执行流程是首先去除了所有请求的csrf认证,然后把视图类的request对象变成了新的request对象,新的reqeust对象是DRF的,但是以前Django的request对象用起来是一样的,同时把新的reqeust对象放到了视图类的对象中,然......
  • DRF之异常捕获源码分析
    DRF之异常捕获源码分析【一】异常捕获介绍DjangoRestFramework(DRF)是一个用于构建WebAPI的强大框架,它提供了一种处理异常的机制,使开发人员能够捕获和处理各种异常情况。DRF中的异常捕获类是用于捕获和处理这些异常的关键组件之一。【二】异常捕获流程分析#全局异常处理......
  • DRF之JWT签发Token源码分析
    DRF之JWT签发Token源码分析【一】JWT介绍JWT(JSONWebToken)是一种用于身份认证和授权的开放标准(RFC7519)。它基于JSON格式定义了一种安全的令牌,用于在客户端和服务器之间传输信息。【二】JWT三段式JWT(JSONWebToken)是一种用于身份认证和授权的开放标准(RFC7519)。它基于......
  • DRF之分页类源码分析
    DRF之分页类源码分析【一】分页类介绍DjangoRESTframework(DRF)是一个用于构建WebAPI的强大工具,它提供了分页功能,使你能够控制API响应的数据量。在DRF中,分页功能由分页类(PaginatorClass)来管理。【二】内置分页类在DRF中,分页类通常位于rest_framework.pagination模块中,它......
  • DRF之过滤类源码分析
    DRF之过滤类源码分析【一】过滤类介绍及BaseFilterBackendDjangoRESTframework(DRF)中的过滤类允许你在API视图中对查询进行过滤,以根据特定条件筛选结果集。过滤类是DRF的一部分,它允许你轻松地添加各种过滤选项,以满足不同用例的需求。classBaseFilterBackend:"""......