django Rest Framework----认证/访问权限控制/访问频率限制 执行流程 Authentication/Permissions/Throttling 源码分析
url:
url(r'books/$',views.BookView.as_view({'get':'list','post':'create'})) 为例
当django启动的时候,会调用执行view.BookView.as_view()方法,拿到as_view的返回值view
url(r'books/$',View.view)
当用户访问books/的时候,会执行View.view(). 执行APIView.dispatch()
当用户访问books/时,django拿到request,然后对request进行了重新封装
并且进行用户认证
url(r'books/$',View.view) ---> 执行 self.dispatch()
APIView.dispatch()
def dispatch(self, request, *args, **kwargs):
...
request = self.initialize_request(request, *args, **kwargs)
self.request = request
try:
self.initial(request, *args, **kwargs)
....
request = self.initialize_request(request, *args, **kwargs)
def initialize_request(self, request, *args, **kwargs):
#返回一个Request对象
return Request(
...
authenticators=self.get_authenticators(),
...
) def get_authenticators(self):
# 循环视图类authentication_classes
# 使用列表推导式,生成每一个实例对象
return [auth() for auth in self.authentication_classes]
回到dispatch()中,继续向下执行self.inital(request,*args,**kwags)
def initial(self, request, *args, **kwargs):
...
# 认证
self.perform_authentication(request)
# 权限
self.check_permissions(request)
# 访问频率限制
self.check_throttles(request)
对于用户认证,我们主要看 self.perform_authentication(request) 干了什么
def perform_authentication(self, request):
# 调用了request.user 属性方法
request.user
@property
def user(self): if not hasattr(self, '_user'):
with wrap_attributeerrors():
# 调用 _authenticate 此时的self是request对象
self._authenticate()
return self._user def _authenticate(self):
# 此时的self是request ,authenticator每一个验证类对象
for authenticator in self.authenticators:
try:
# 使用authenticator调用它的authenticate() 返回一个元组
#元组的第一个值是request.user,第二个值是request.auth
user_auth_tuple = authenticator.authenticate(self)
except exceptions.APIException:
# 如果没有验证通过,抛出异常
self._not_authenticated()
raise # 如果 user_auth_tuple 不为空的话,证明authenticator.authenticate(self) 返回了数据
# **** 有多个验证类的话,最后一个认证类返回值,其他验证类不要返回
# 否则,这个验证类之后的所有验证类都不会被执行
# 如果返回值不为None,赋值后 将会跳出循环
if user_auth_tuple is not None:
self._authenticator = authenticator
# 进行赋值
self.user, self.auth = user_auth_tuple
# 跳出for循环, 验证通过
return self._not_authenticated()
认证执行流程:
1. 查看settings.py中是否配置了作用于全局的REST_FRAMEWORK配置,如果有,就是用全局
2. 如果settings.py没有配置,就去视图类中(本例是BookView)查看是否配置了authentication_classes
3. 以上都没有配置,就是用默认的,在APIView中配置
自定义一个认证
class BookAuthen():
def authenticate(self,request):
#获取token,检验token是否正确,如果正确则,验证通过
#否则抛出异常
token_val = request.GET.get('token')
user_obj = models.User.objects.filter(token__token=token_val).first()
if user_obj:
return user_obj.name,token_val
else:
raise exceptions.AuthenticationFailed
def authenticate_header(self,request):
pass class BookView(ModelViewSet):
# 如果提供,就执行BookAuthen,如果没有提供,使用APIView提供的
authentication_classes = [BookAuthen,]
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
全局配置(settings.py):
REST_FRAMEWORK= {
'DEFAULT_AUTHENTICATION_CLASSES': (
'bookmanage.auth.authen.BookAuthen',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
)
}
默认配置(APIView):
class APIView(View):
...
# 首先api_settings没有DEFAULT_AUTHENTICATION_CLASSES 所以会调用apisetting.__getattr__()
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
...
二、访问频率限制
访问频率限制和用户认证流程几乎相同
首先看url
url(r'books/$',views.BookView.as_view({'get':'list','post':'create'})) 为例
django启动时
去执行BookView.as_view()方法--->APIView.as_view()-->最终返回的是APIView.view
url(r'books/$',views.BookView.as_view({'get':'list','post':'create'}))
url(r'books/$',APIView.view) 用户访问时
执行APIView.view(),其中它调用了父类的as_view(),实际上什么都没做
执行self.dispatch(),执行的是APIView.dispatch() self.initial(request, *args, **kwargs)
调用了 --> self.check_throttles(request) #此时的self是BookView视图类
dispatch()中,self.inital(request,*args,**kwags) --> self.check_throttles(request)
def get_throttles(self):
"""
遍历视图类中的throttle_classes
拿到每一个自定义访问频率限制类的实例对象
"""
return [throttle() for throttle in self.throttle_classes] def check_throttles(self, request):
for throttle in self.get_throttles():
# 拿到自定义访问频率限制类的实例对象,调用allow_request() if not throttle.allow_request(request, self):
# 如果没有通过验证,执行self.throttled()抛出异常
self.throttled(request, throttle.wait())
自定义访问频率限制类
# 限制IP频繁访问
class VisitThrottle(object):
detail = "访问频率不正常"
def allow_request(self,request, obj):
now_time = str(time.time())
if request.session.get('visittime'):
visited = request.session.get('visittime')
visited.append(now_time)
request.session['visittime'] = visited
if len(visited) >= 20:
first = visited[-2]
last = visited[-1]
time_ = time.gmtime(float(last) - float(first))
print(time_)
if time_.tm_min > 1:
request.session['visittime'] = []
return True
elif time_.tm_min <= 1:
raise exceptions.Throttled(detail=self.detail) else:
request.session['visittime'] = [now_time,]
print(request.META.get('REMOTE_ADDR')) return True class BookView(ModelViewSet):
#在视图类中配置自定义频率访问组件
throttle_classes = [VisitThrottle]
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
默认访问频率限制
由于每一个视图类都是继承自APIView,
如果配置throttle_classes,就使用自定义的
如果没配置throttle_classes,APIView配置了默认的
class APIView(View):
.... # 由于api_settings没有DEFAULT_THROTTLE_CLASSES,会调用api_setting的__getattr__()
throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES .... api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS) class APISettings(object):
def __init__(self, user_settings=None, defaults=None, import_strings=None):
#不会进入
if user_settings:
self._user_settings = self.__check_user_settings(user_settings)
# 将DEFAULTS 复制给 self.defaults
self.defaults = defaults or DEFAULTS @property
def user_settings(self):
if not hasattr(self, '_user_settings'):
self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
return self._user_settings def __getattr__(self, attr):
if attr not in self.defaults:
raise AttributeError("Invalid API setting: '%s'" % attr)
try:
# self.user_settings : 它从settings.py中取找 是否存在 REST_FRAMEWORK配置项
# 如果有,因为他是一个字典,取[DEFAULT_THROTTLE_CLASSES]对应的路径自定义访问频率类
val = self.user_settings[attr]
except KeyError: # 如果没有,就使用默认的
# self.defaults[DEFAULT_THROTTLE_CLASSES]
val = self.defaults[attr] ....
return val
全局配置
1. 此时,应该将自定义的访问频率组件提取出来单独放在一个py文件中
2. 指定路径类
3. 所有的url访问都会进行访问频率限制
REST_FRAMEWORK= {
'DEFAULT_AUTHENTICATION_CLASSES': (
'bookmanage.auth.authen.BookAuthen',
),
'DEFAULT_THROTTLE_CLASSES':(
'bookmanage.auth.throttle.VisitThrottle'
)
}
django Rest Framework----认证/访问权限控制/访问频率限制 执行流程 Authentication/Permissions/Throttling 源码分析的更多相关文章
- Django Rest Framework(认证、权限、限制访问频率)
阅读原文Django Rest Framework(认证.权限.限制访问频率) django_rest_framework doc django_redis cache doc
- 04 Django REST Framework 认证、权限和限制
目前,我们的API对谁可以编辑或删除代码段没有任何限制.我们希望有更高级的行为,以确保: 代码片段始终与创建者相关联. 只有通过身份验证的用户可以创建片段. 只有代码片段的创建者可以更新或删除它. 未 ...
- c/c++再学习:C++中public、protect、private的访问权限控制
C++中public.protect.private的访问权限控制 访问权限 一个类的public成员变量.成员函数,可以通过类的成员函数.类的实例变量进行访问 一个类的protected成员变量.成 ...
- ASP.NET Core[源码分析篇] - 认证
追本溯源,从使用开始 首先看一下我们的通常是如何使用微软自带的认证,一般在Startup里面配置我们所需的依赖认证服务,这里通过JWT的认证方式讲解 public void ConfigureServ ...
- ASP.NET Core[源码分析篇] - Authentication认证
原文:ASP.NET Core[源码分析篇] - Authentication认证 追本溯源,从使用开始 首先看一下我们通常是如何使用微软自带的认证,一般在Startup里面配置我们所需的依赖认证服务 ...
- Django REST framework认证权限和限制和频率
认证.权限和限制 身份验证是将传入请求与一组标识凭据(例如请求来自的用户或其签名的令牌)相关联的机制.然后 权限 和 限制 组件决定是否拒绝这个请求. 简单来说就是: 认证确定了你是谁 权限确定你能不 ...
- MongoDB 安全和访问权限控制
MongoDB的访问控制能够有效保证数据库的安全,访问控制是指绑定Application监听的IP地址,设置监听端口,使用账户和密码登录 一,访问控制的参数 1,绑定IP地址 mongod 参数:-- ...
- IAM:亚马逊访问权限控制
IAM的策略.用户->服务器(仓库.业务体) IAM:亚马逊访问权限控制(AWS Identity and Access Management )IAM使您能够安全地控制用户对 AWS 服务和资 ...
- (转)浅析Java中的访问权限控制
原文地址: http://www.cnblogs.com/dolphin0520/p/3734915.html 今天我们来一起了解一下Java语言中的访问权限控制.在讨论访问权限控制之前,先来讨论一下 ...
随机推荐
- MT【124】利用柯西求最值
已知 \(a\) 为常数,函数\(f(x)=\dfrac{x}{\sqrt{a-x^2}-\sqrt{1-x^2}}\) 的最小值为\(-\dfrac{2}{3}\),则 \(a\) 的取值范围___ ...
- 洛谷 P1072 Hankson 的趣味题 解题报告
P1072 \(Hankson\)的趣味题 题目大意:已知有\(n\)组\(a0,a1,b0,b1\),求满足\((x,a0)=a1\),\([x,b0]=b1\)的\(x\)的个数. 数据范围:\( ...
- bzoj 3772 :精神污染 线段树+打标记 or 主席树
3772: 精神污染 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 315 Solved: 87[Submit][Status][Discuss] D ...
- 【bzoj2795】【Poi2012】A Horrible Poem
题解: 询问区间的整循环节 设区间长度为$n$ 如果有循环节长为$x$和$y$,那由斐蜀定理得$gcd(x,y)$也一定为一个循环节: 假设最小的循环节长为$mn$,那么对于任何循环节长$x$,一定$ ...
- 【数学】【CF1091D】 New Year and the Permutation Concatenation
Description 给定一个数 \(n\),将所有 \(1~\sim~n\) 的排列按照字典序放到一个序列中,求有多少长度为 \(n\) 的子序列 \(p_i~p_{i+1}~\dots~p_{i ...
- HOJ 13102 Super Shuttle (圆的反演变换)
HOJ 13102 Super Shuttle 链接:http://49.123.82.55/online/?action=problem&type=show&id=13102 题意: ...
- DNS系统的解析原理
根据网络通讯原理,对于Router设备是通过IP地址进行路径的Forward:当通过域名(主机名)访问远程主机时,必须将相应的主机名解析为IP地址,DNS服务器就充当了这个角色. DNS的工作原理: ...
- Linux基础命令之grep
grep : 根据pattern(模式)搜索文本,并将符合模式的文本行显示出来,并不会修改原文件. 用法: grep [options] ‘ pattern ‘ /file #也可 ...
- python的reduce函数的使用方法详解以及使用案例,相加,相乘(处理一个序列,然后把序列进程合并操作)
1.求列表的数字相加之和,还是之前的习惯,写for循环来实现 num_1=[1,2,3,4,5,6,7,8,9] a=0 for n in num_1: #a=a+n a+=n print (a) C ...
- Kubernetes init container
目录 简介 配置 init container与应用容器的区别 简介 在很多应用场景中,应用在启动之前都需要进行如下初始化操作: 等待其他关联组件正确运行(例如数据库或某个后台服务) 基于环境变量或配 ...