drf 认证、权限、频率

drf 认证、权限、频率

1、权限类使用

使用步骤

  1. 写一个类,继承BasePermission
  2. 重写has_permission方法
  3. 在方法中校验用户是否有权限(request.user就是当前登录用户)
  4. 如果有权限,返回True,没有权限,返回False
  5. self.message 是给前端的提示信息
  6. 局部使用,全局使用,局部禁用

修改user表 创建用户类型字段, 可以是choise 选项 也可以通过 外键关联一个 用户类型表
用户模型类

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

permission.py

class UserType(BasePermission):
    #重写 该方法
    def has_permission(self, request, view):
        #通过 字段判断 用户类型
        if request.user.user_type == 3:
            return True

        else:
            self.message = '您是%s 需要开通超级用户才能访问' % request.user.get_user_type_display()
            return False

2、频率类使用

使用步骤

  1. 写一个类:继承SimpleRateThrottle

  2. 重写get_cache_key,返回唯一的字符串,会以这个字符串做频率限制

  3. 写一个类属性scop=‘随意写’,必须要跟配置文件对象

  4. 配置文件中写

     'DEFAULT_THROTTLE_RATES': {
            '随意写': '3/m'  # 3/h  3/s  3/d
        	}
    
  5. 局部配置,全局配置,局部禁用

throttl.py

from rest_framework.throttling import BaseThrottle, SimpleRateThrottle
class MyThrottling(SimpleRateThrottle):  # 我们继承SimpleRateThrottle去写,而不是继承BaseThrottle去写
    # 类属性,这个类属性可以随意命名,但要跟配置文件对应
    scope = 'luffy'
    def get_cache_key(self, request, view):
        # 返回什么,频率就以什么做限制
        # 可以通过用户id限制
        # 可以通过ip地址限制
        return request.META.get('REMOTE_ADDR')

setting.py

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES':['app01.throttling.MyThrottling'],
    'DEFAULT_THROTTLE_RATES': {
        'luffy': '3/m'
    }
}

3、认证 权限 频率 全局、局部 配置

局部配置

authentication_classes = [] # 认证
permission_classes = []  # 权限
throttle_classes = []  # 频率

全局配置

REST_FRAMEWORK = {
    # 登录全局配置
    'DEFAULT_AUTHENTICATION_CLASSES': ['app01.auth.Login_Auth', ],

    # 权限 全局 配置
    # 'DEFAULT_PERMISSION_CLASSES':['app01.permission.UserType'],

    # 频率 全局配置
    'DEFAULT_THROTTLE_CLASSES': ['app01.throttl.Throttle'],
    'DEFAULT_THROTTLE_RATES': {
        # 每分钟 访问五次
        'DaLao': '5/m'
    }
}

4、 认证源码分析

# 写个认证类,重写某个方法,配置在视图类上,就有认证了---》认证类加了,在视图类的方法中,request.user就是当前登录用户---》猜认证类的执行,是在在视图类的方法之前执行的
# 源码分析:
	-之前咱们读APIView的执行流程---》包装了新的request,执行了3大认证,执行视图类的方法,处理了全局异常
    -入口:APIView的dispatch
    -APIView的dispatch的496行上下:self.initial(request, *args, **kwargs)
    -APIView的initial
    -413行上下:有三句话,分别是:认证,权限,频率
    	self.perform_authentication(request)
        self.check_permissions(request)
        self.check_throttles(request)
    -读认证类的源码---》APIView的perform_authentication(request)315行上下
    	def perform_authentication(self, request):
        	request.user  # 新的request
    -request是新的request---》Request类中找user属性(方法),是个方法包装成了数据属性
	-来到Request类中找:220def user(self):
            if not hasattr(self, '_user'): # Request类的对象中反射_user
                with wrap_attributeerrors():
                    self._authenticate()  # 第一次会走这个代码
            return self._user
    -Request的self._authenticate()---373def _authenticate(self):
            for authenticator in self.authenticators: # 配置在视图类中所有的认证类的对象 
                try:
                    #(user_token.user, token)
                    user_auth_tuple = authenticator.authenticate(self) # 调用认证类对象的authenticate
                except exceptions.APIException:
                    self._not_authenticated()
                    raise

                if user_auth_tuple is not None:
                    self._authenticator = authenticator # 忽略
                    self.user, self.auth = user_auth_tuple # 解压赋值
                    return
			  # 认证类可以配置多个,但是如果有一个返回了两个值,后续的就不执行了
            self._not_authenticated()
            
            
    # 总结:认证类,要重写authenticate方法,认证通过返回两个值或None,认证不通过抛AuthenticationFailed(继承了APIException)异常

5、权限源码分析

-先读最简单的权限执行流程---》APIView的check_permissions(request)325行上下
    def check_permissions(self, request):
        for permission in self.get_permissions():
            # permission是咱们配置在视图类中权限类的对象,对象调用它的绑定方法has_permission
            # 对象调用自己的绑定方法会把自己传入(权限类的对象,request,视图类的对象)
            if not permission.has_permission(request, self):
                self.permission_denied(
                    request,
                    message=getattr(permission, 'message', None),
                    code=getattr(permission, 'code', None)
                )
                
   -APIVIew的self.get_permissions()273行上下
	return [permission() for permission in self.permission_classes]
   -self.permission_classes 就是咱们在视图类中配的权限类的列表
   -所以这个get_permissions返回的是 咱们在视图类中配的权限类的对象列表[UserTypePermession(),]


	# 总结:权限类源码
    	-为什么要写一个类,重写has_permission方法,有三个参数,为什么一定要return TrueFalse,messgage可以做什么用

6、简单读频率类源码

# 源码分析:
	-之前咱们读APIView的执行流程---》包装了新的request,执行了3大认证,执行视图类的方法,处理了全局异常
    -入口:APIView的dispatch
    -APIView的dispatch的496行上下:self.initial(request, *args, **kwargs)
    -APIView的initial
    -413行上下:有三句话,分别是:认证,权限,频率
    	self.perform_authentication(request)
        self.check_permissions(request)
        self.check_throttles(request)
    -APIView的check_throttles:351上下
        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())
                    
                    
   -总结:要写频率类,必须重写allow_request方法,返回True(没有到频率的限制)或False(到了频率的限制)

7、鸭子类型

走路像鸭子,说话像鸭子,它就是鸭子

指的是面向对中,子类不需要显示的继承某个类,只要有某个方法和属性,哪我就属于这个类
假设没有鸭子类,Duck类,有两个方法,run,speak方法
假设又又一个普通鸭子类,PDuck,如果它也是鸭子,它需要继承Duck类,只要继承了鸭子类,什么都不需要写,普通鸭子类的对象就是鸭子这种类型,如果不继承,普通鸭子类的对象就不是,鸭子这种类型

假设又有一个唐老鸭子类,TDuck,如果它也是鸭子,它需要继承Duck类,只要继承了鸭子类,什么都不需要写,唐老鸭子类的对象就是鸭子这种类型;如果不继承,唐老鸭子类的对象就不是鸭子这种类型

python 不推崇这个,它推崇鸭子类型,指的是
不需要显示的继承某个类,只要我的类中又run和speak方法,我就是鸭子这个类

有小问题:如果使用python鸭子类型的写法,如果方法写错了,它就不是这个类型了,会有问题
python为了解决这个问题:

  1. abc模块,装饰后,必须重写方法,不重写就报错
  2. drf源码中使用,父类中写这个方法,但没有具体实现,直接抛异常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值