权限控制
前言
用户验证用户权限,根据不同访问权限控制对不同内容的访问。
建议了解视图、token验证的内容。
使用流程
- 自定义访问权限类,继承
BasePermission
,重写has_permission()
方法,如果权限通过,就返回True
,不通过就返回False
。has_permission()
方法接受两个参数,分别是request
和view
,也就是视图类的实例化本身。
- 配置。
局部配置:
permission_classes = [MyUserPermission]
全局配置:
REST_FRAMEWORK={
'DEFAULT_PERMISSION_CLASSES': ['libs.MyAuth.UserPermission',],
}
示例
class SVIPPermission(BasePermission): # 推荐继承BasePermission类
# message = 'You do not have permission to perform this action.'#默认值
message = '无此权限!!!'
def has_permission(self, request, view):
if request.user.user_type == 3:
return False # False为没权限
# view.queryset = # 可以使用这种方式控制视图中要处理的数据(根据不同权限)
return True # True为有权限
源码分析
进入dispatch
函数,查看initial
方法(执行三大验证)中的check_permissions
方法:
self.check_permissions(request)
将会根据request
中的用户内容进行权限控制。
由上可知,permission_classes
要么读取配置文件中的DEFAULT_PERMISSION_CLASSES
(全局),要么就在视图类中直接对permission_classes
赋值(局部)。
节流限制
前言
控制网站访问频率。
使用流程
- 自定义限制类,继承
BaseThrottle
。 - 指定从配置文件中要读取的scope(key),形式为
scope="key"
全局配置:
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
],
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/day'
}
}
局部配置:
throttle_classes = [UserRateThrottle]
就比如UserRateThrottle
,继承了SimpleRateThrottle
,指定了它所限制的scope
,重写了get_cache_key
方法。
源码分析
在APIView
的initial
方法中,三大验证还剩下最后一个没有分析,那就是访问频率验证,如下图:
接下来让我们查看check_throttles
,可以看到,验证访问频率的时候,调用的方法为频率验证类的allow_request
方法。
其中get_throttles
用的还是老套路:
示例
自定义一个频率限制类:
from rest_framework.throttling import BaseThrottle
import time
# 存放访问记录(一般放数据库或者缓存中)
VISIT_RECORD = {}
class VisitThrottle(BaseThrottle):
def __init__(self):
self.history = None
def allow_request(self, request, view):
# 1. 获取用户ip
remote_addr = request.META.get("REMOTE_ADDR")
# 2. 添加到访问记录中
ctime = time.time()
# 当VISIT_RECORD中没有这个记录,可以直接访问,添加一个记录
if remote_addr not in VISIT_RECORD:
VISIT_RECORD[remote_addr] = [ctime, ]
return True
history = VISIT_RECORD.get(remote_addr)
self.history = history
# 拿到最后历史记录里面的最后一个时间,如果最后一个时间小于当前时间-60(一分钟之前的记录)
while history and history[-1] < ctime - 60:
history.pop()
if len(history) < 3: # 允许
history.insert(0, ctime)
return True
return False # False表示访问频率太高被限制
def wait(self):
"""
还需要等多少秒可以访问
:return:
"""
ctime = time.time()
return 60 - (ctime - self.history[-1])
注意:官方内置的 SimpleRateThrottle
类中对scope
的处理值得一看。