首页 > 编程语言 >自定义频率-权限 频率执行源码分析-全局异常处理-自动生成接口文档-RBAC

自定义频率-权限 频率执行源码分析-全局异常处理-自动生成接口文档-RBAC

时间:2022-08-23 19:11:21浏览次数:146  
标签:自定义 ip self request --- 源码 频率 权限 history

自定义频率类

 

# 自定义的逻辑
  1)取出访问者ip   {192.168.1.12:[访问时间3,访问时间2,访问时间1],192.168.1.12:[],192.168.1.14:[]}
  2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
  3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
  4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
  5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败

 

具体实现

 

from rest_framework.throttling import BaseThrottle
class MyThrottling():
    VISIT_RECORD = {}

    def __init__(self):
        self.history = None
    def allow_request(self, request, view):
        # (1)取出访问者ip
        ip = request.META.get('REMOTE_ADDR')
        import time
        ctime = time.time()
        # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问
        if ip not in self.VISIT_RECORD:
            self.VISIT_RECORD[ip] = [ctime, ]
            return True
        self.history = self.VISIT_RECORD.get(ip)
        # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
        while self.history and ctime - self.history[-1] > 60:
            self.history.pop()
        # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
        # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
        if len(self.history) < 3:
            self.history.insert(0, ctime)
            return True
        else:
            return False

    def wait(self):
        import time
        ctime = time.time()
        return 60 - (ctime - self.history[-1])

 

权限,频率执行源码分析

权限源码执行流程
# APIView的dispatch---》self.initial(request, *args, **kwargs)---》415行self.check_permissions(request)--->
    def check_permissions(self, request):
        for permission in self.get_permissions(): #配在视图类上的权限类列表对象
            if not permission.has_permission(request, self):
                self.permission_denied(
                    request,
                    message=getattr(permission, 'message', None),
                    code=getattr(permission, 'code', None)
                )

频率源码执行流程
# APIView的dispatch---》self.initial(request, *args, **kwargs)---》416行self.check_throttles(request)--->
  def check_throttles(self, request):
        throttle_durations = []
        for throttle in self.get_throttles(): # 配在视图类上频率类列表 频率类的对象
            if not throttle.allow_request(request, self):
                throttle_durations.append(throttle.wait())
        if throttle_durations:
            durations = [
                duration for duration in throttle_durations
                if duration is not None
            ]

            duration = max(durations, default=None)
            self.throttled(request, duration)
            
# 你写的频率类一定要重写allow_request,返回True就是没有频率限制住,返回False就是被频率限制了

# 咱们第一天写的,继承SimpleRateThrottle---》它肯定重写了allow_request---》今天写的逻辑跟源码一样
SimpleRateThrottle---》allow_request---》
    def __init__(self):
        if not getattr(self, 'rate', None):
            # self.rate 现在是  '3/m'
            self.rate = self.get_rate()
        # 3                   60
        self.num_requests, self.duration = self.parse_rate(self.rate)
    def allow_request(self, request, view):
        if self.rate is None:  # 只要配在文件配了,它就有值,在init中
            return True

        # 现在的唯一字符串
        # ip地址
        self.key = self.get_cache_key(request, view)
        if self.key is None:
            return True

        # [时间2,时间1]
        self.history = self.cache.get(self.key, [])
        self.now = self.timer()
        while self.history and self.history[-1] <= self.now - self.duration:
            self.history.pop() #把所有超过60的数据都剔除,self.history只剩60s以内的访问时间
        if len(self.history) >= self.num_requests:  #大于等于配置的数字3 
            return self.throttle_failure() # return False
        return self.throttle_success()  # 把当前时间插入,retrun True

全局异常处理

 drf配置文件中,已经配置了,但是它不符合咱们的要求 drf的配置文件:'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler', 如果抛了异常,就会执行exception_handler函数

 重新写一个函数,如果出了异常,执行我们的函数

 drf默认的异常处理,只处理了drf自己的异常:所有drf中抛的异常,都有detail,django的异常,抛出很长的xml数据


{
    "detail": "小伙子,你错了"
}

{    
    code:999
     msg:"小伙子,你错了"
}

使用步骤

# 第一步:写一个函数
from rest_framework.views import exception_handler
from rest_framework.response import Response
def common_exception_handler(exc, context):
    # 正常来讲,在这里需要记录日志---》如何在django中记录日志后面讲
    # 日志记录,越详细越好:哪个用户(id,ip),在什么时间,执行哪个视图函数时报了错,请求地址是什么
    print(context['view'])  #视图类的对象
    print(context['request']) #当前请求的对象----》ip,用户id,当前时间,请求地址来
    view=context['view']
    request=context['request']
    print('ip地址为:%s的用户,访问:%s 视图类,报错了,请求地址是:%s'%(request.META.get('REMOTE_ADDR'),str(view),request.path))

    response=exception_handler(exc, context)
    if response: # 这是drf的异常,其实人家已经处理了,但是不符合我的格式  {code:999,msg:错误}
        res=Response({'code':999,'msg':response.data.get('detail')})
    else:
        # res=Response({'code':998,'msg':'服务器错误,请联系系统管理员'})
        res=Response({'code':998,'msg':str(exc)})

    return res
# 第二步:把函数配置在配置文件中
    REST_FRAMEWORK = {
    # 自己写的全局异常捕获
        'EXCEPTION_HANDLER': 'app01.exceptions.common_exception_handler',
    }

自动生成接口文档

# 后端人员,写好接口,提供接口文档给前端用

# 如何编写接口文档
    -使用word写,md写----》提交到git上
    -公司有接口文档平台---》后端人员在文档平台录入数据---》公司自己开发,yapi(百度开源),第三方
        -https://zhuanlan.zhihu.com/p/366025001  自己搭建yapi
        -https://www.showdoc.com.cn/  第三方平台
    - 自动生成接口文档---》项目写好了,一键生成接口文档----》一键生成---》导出---》导入到yapi

# drf中自动生成接口文档
    -coreapi,swagger(更通用一些,go,java)
    -安装 pip3 install coreapi
    -在项目中配置     
        -加入路由:
        from rest_framework.documentation import include_docs_urls
        urlpatterns = [
            path('docs/', include_docs_urls(title='站点页面标题'))
        ]
        -配置文件中配置
        REST_FRAMEWORK = {
         'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',

        }
        
        -尽管写接口,写注释,会自动生成
    

RBAC

# RBAC  是基于角色的访问控制(Role-Based Access Control )在 RBAC  中,
权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便


# 这种设计,在公司内部系统用的多,对外的系统基本不用

# 权限:真正的权限,比如发工资,招人,申请测试机
# 角色:(组,部门) 角色下有很多员工
# 用户:一个个的人

# 用户和角色关系是多对多,中间表
# 权限和角色关系是多对多,中间表
# 权限和用户的中间表


#前后端分离项目控制权限---》权限类中
#前后端混合
    -django框架在公司里用的很多,写内部项目,肯定要用权限控制,用的就是rbac,自己实现一套,django内置了后台管理,自带rbac(admin+auth)
    -基于django的admin二次开发
    -美化:xadmin(基本不用了,2.x以后django不兼容多,作者弃坑了)
    -simpleui:
    -django+drf+vue=djagnovueadmin  一款前后端分离的自带rbac的后台管理框架
    
    
    
# django的admin基于rbac
    -auth_user  #用户表
    -auth_permission #权限表
    -auth_group  #组,角色表
    
    -auth_user_groups   # 用户和组中间表
    -auth_group_permissions  #组和权限中间表
    -auth_user_user_permissions #用户和权限中间表

 

标签:自定义,ip,self,request,---,源码,频率,权限,history
From: https://www.cnblogs.com/wql0817/p/16617456.html

相关文章

  • Banner自定义
    Banner1.简介SpringBootLogo以及版本信息:${spring-boot.version}、${spring-boot.formatted-version},参考banner.txt文件;Banner大全地址:https://www.bootschool......
  • 使用自定义注解实现接口防重复提交
    后端实现防重复提交的方式有很多中,大颗粒级别可以使用Redis或nginx,也就是所谓的滑动窗口、令牌桶等,但是这些大颗粒只能实现同一接口同一IP同一用户的重复提交,不能对请......
  • 树莓派搭建WordPress博客:为博客网站配置自定义域名 11/11
    在上一篇文章中,我们通过在服务器上设置新的域名,并将新域名的指向引导到cpolar的数据通道后台入口端,让新域名的链接生效。接下来,我们就要在本地树莓派端,对cpolar进行设置,让c......
  • 自定义Mybatis拦截器实现自动添加创建人修改人等公共字段
    摘要本文通过自定义Mybatis拦截器拦截Executor接口实现在插入和修改操作时自动添加创建人修改人等公共字段,话不多说,直接上代码定义Mybatis拦截器packagecom.syb.spring......
  • 数字化培训、知识库、考学一体平台@附源码
    前言随着信息化的进一步推进,目前各行各业都在进行数字化转型,本人从事过医疗、政务等系统的研发,和客户深入交流过日常办公中“知识”的重要性,再加上现在倡导的互联互通、数......
  • 源码编译安装 git
    1、下载解压git源代码curl-Ohttps://mirrors.edge.kernel.org/pub/software/scm/git/git-2.37.2.tar.gztar-xvfgit-2.37.2.tar.gzcdgit-2.37.22、安装依赖包......
  • VUE学习-自定义修饰符
    自定义修饰符组件constmyComponent={template:`<inputtype="text":value="modelValue"@input="emitValue"/>`,props:{modelValue:String,......
  • 【SpringBoot】自定义注解实现yml格式配置文件注入
    1.创建一个starter项目(非必须,主要更好分离代码)2.创建注解文件@YamlSource@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpu......
  • vue自定义指令的使用
    1、背景:想通过自定义指令v-hasHelp控制页面右上角是否出现帮助按钮,点击按钮可以跳转外部链接。用自定义指令的目的是方便。2、先在自己的项目中注册使用hasHelpindex.j......
  • vue3源码学习
    建议先通过官方指南了解3.0都干了啥、解决了什么问题。然后才是阅读其源码(通过利器),进阶了解它是如何实现的。https://juejin.cn/post/6925668019884523534......