drf(django rest-framework)认证组件

复习

HyperlinkedIdentityField
​```python
功能:快速生成连接
1. publish = serializers.HyperlinkedIdentityField(view_name='ttt', lookup_field='publish_id', lookup_url_kwarg='pkk')
view_name:路由的别名,look_up_field:根据表的哪个字段,来拼路径
lookup_url_kwarg:反向解析有名分组的名字
2.写路由:url(r'^publish/(?P<pk>\d+)',views.Publish.as_view(),name="ttt")
3.实例化序列化类的时候,需要把request对象传过去
book_ser = BookSerializer(ret,many=True,context={'request':request})

数据校验

生成序列化类对象的时候,把要校验的数据(字典:前端传过来)传过来
-ser = BookSerializer(data=request.data)
-ser.is_valid()
-error_messages

认证简介

什么是验证
认证是否登陆 为什么要有认证
有些操作需登陆后才能访问 如何用认证:
也就是在使用功能前,验证其是否是登陆状态

属性,方法的查找顺序

对象>>>>类>>>>>父类

CBV知识点

一.路由层:
url(r'^books/$', views.Books.as_view()), 二.项目启动时,就会执行Books.as_view()
#as_view()源码,csrf_exempt局部禁用csrf,也就是说继承了drf的APIView的CBV都是不需要csrf认证的
@classmethod
def as_view(cls, **initkwargs):
...
#调用了父类的as_view方法,也就是View的as_view方法
view = super(APIView, cls).as_view(**initkwargs)
...
return csrf_exempt(view) #View的as_view方法,闭包函数,返回了view的内存地址
@classonlymethod
def as_view(cls, **initkwargs):
...
def view(request, *args, **kwargs):
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
return self.dispatch(request, *args, **kwargs)
...
return view
三.所以项目启动时路由层的
url(r'^books/$', views.Books.as_view())相当于url(r'^books/$', views.Books.view) 四.当有请求过来时,系统调用Books.view方法
def view(request, *args, **kwargs):
....
#view方法返回了dispatch方法,本质了调用了dispatch方法
return self.dispatch(request, *args, **kwargs) 五.drf的dispatch源码
def dispatch(self, request, *args, **kwargs):
...
'''
self.initialize_request(request, *args, **kwargs)封装了原生request请求
返回了新的request对象,以前的request.GET 相当于新对象的request.query_params def query_params(self):
...
return self._request.GET 新的request重写了__getattr__(当.方法调用属性且当属性不存在时自动触发)
def __getattr__(self, attr):
try:
return getattr(self._request, attr)
except AttributeError:
return self.__getattribute__(attr)
request = self.initialize_request(request, *args, **kwargs)
self.request = request
#所以当我们使用request.GET方法时,新对象没有GET方法,触发了__getattr__方法,执行到语句getattr(self._request, attr)获得原request对象的GET属性
'''
try:
#initial内部进行了认证,权限,频率检验
self.initial(request, *args, **kwargs)
if request.method.lower() in self.http_method_names:
#执行我们自己定义的方法
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed response = handler(request, *args, **kwargs) except Exception as exc:
response = self.handle_exception(exc) self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response

总结

drf的APIView与django View的相同点
本质都是执行了dispatch方法 drf的APIView与django View的不同点
drf的APIView继承了View
派生了自己的dispatch方法
在方法中对原生request对象进行了封装 总结:CBV的本质就是执行了父类的dispatch方法
dispatch方法中会检索我们自己的CBV是否有get,post等方法
检索到了就会执行
APIView 的dispatch方法在检测之前会执行self.initial(request, *args, **kwargs)方法
此方法内部进行了认证,频率,权限控制
dispatch相当于我们学的装饰器,在执行目标函数之前或之后,可以添加我们需要的功能

认证组件:

drf的认证组件,本质就是在dispatch方法通过反射getattr()找到我们定义的方法前,增加了认证功能
#initial源码 def initial(self, request, *args, **kwargs):
...
# Ensure that the incoming request is permitted
#认证
self.perform_authentication(request)
#权限
self.check_permissions(request)
#频率
self.check_throttles(request) #认证功能源码
'''
只执行了request.user,user是私有属性,即方法被装饰成属性
此处的request已经被封装过了(封装函数在认证函数之前)
def dispatch(self, request, *args, **kwargs):
...
#封装函数
request = self.initialize_request(request, *args, **kwargs)
...
try:
#认证函数
self.initial(request, *args, **kwargs)
'''
def perform_authentication(self, request):
request.user #request.user
@property
def user(self):
...
#当我们认证通过返回了user_auth_tuple
#self.user, self.auth = user_auth_tuple会触发user的set方法
'''
@user.setter
def user(self, value):
#request有了_user属性,再调用request.user时就会直接返回request._user
self._user = value
self._request.user = value
'''
#有了_user的属性,直接返回self._user
if not hasattr(self, '_user'):
with wrap_attributeerrors():
#self是request对象,执行了request的_authenticate方法
self._authenticate()
return self._user #self._authenticate(),self是request对象
def _authenticate(self):
#self.authenticators 是request对象初始化的属性
for authenticator in self.authenticators:
try:
user_auth_tuple = authenticator.authenticate(self)
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()

获取 self.authenticators


#Request的__init__函数
class Request(object):
def __init__(self, request, parsers=None, authenticators=None,
negotiator=None, parser_context=None):
assert isinstance(request, HttpRequest), (
'The `request` argument must be an instance of '
'`django.http.HttpRequest`, not `{}.{}`.'
.format(request.__class__.__module__, request.__class__.__name__)
)
...
#等于我们实例化传来的参数或者为空
self.authenticators = authenticators or ()
...
#何时是实例化>>>封装request请求时实例化了Request类
def initialize_request(self, request, *args, **kwargs):
parser_context = self.get_parser_context(request)
#实例化了 Request, authenticators=self.get_authenticators()
return Request(
...
#self为APIView对象
authenticators=self.get_authenticators(),
...
) #APIView的get_authenticators()方法
def get_authenticators(self):
#self为APIView对象,对象的self.authentication_classes属性
#authenticators为列表,里面放着对象
return [auth() for auth in self.authentication_classes] #APIView的authentication_classes属性
class APIView(View):
...
#自己类没有设置的话从api_settings配置文件中找
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES #settings文件,里面俩个没啥用,需要我们自定义authentication_classes,我们自定了话,按照查找顺序,会先从我们的CBV内找
DEFAULT_AUTHENTICATION_CLASSES
Default:
(
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
) 综上:drf提供的authentication_classes无法完成我们的验证需求
我们需要自定义authentication_classes里面存放我们的校验类
1.authentication_classes=[Auth,] 2.get_authenticators(self)方法返回的是我们验证类的对象的列表
def get_authenticators(self):
#self为APIView对象,对象的self.authentication_classes属性
#authenticators为列表,里面放着对象
return [auth() for auth in self.authentication_classes]
3.authenticators=self.get_authenticators()
所以authenticators就是验证类对象的列表
def initialize_request(self, request, *args, **kwargs):
parser_context = self.get_parser_context(request)
#实例化了 Request, authenticators=self.get_authenticators()
return Request(
...
#self为APIView对象
authenticators=self.get_authenticators(),
...
) 4.self.authenticators = authenticators or ()
所以self.authenticators验证类对象的列表
#Request的__init__函数
class Request(object):
def __init__(self, request, parsers=None, authenticators=None,
negotiator=None, parser_context=None):
assert isinstance(request, HttpRequest), (
'The `request` argument must be an instance of '
'`django.http.HttpRequest`, not `{}.{}`.'
.format(request.__class__.__module__, request.__class__.__name__)
)
...
#等于我们实例化传来的参数或者为空
self.authenticators = authenticators or ()
... 5.self.authenticators验证类对象的列表
所以authenticator为验证类的对象
验证类对象执行authenticate方法 #self._authenticate(),self是request对象
def _authenticate(self):
#self.authenticators 是验证类对象的列表,authenticator为验证类对象
for authenticator in self.authenticators:
try:
#验证类对象执行authenticate()方法,验证通过返回一个元组
#self为request对象,这里的参数为request对象
#我们定义自己的authenticate方法时有两个参数,一个是self,一个是request
user_auth_tuple = authenticator.authenticate(self)
#验证不通过抛出异常
except exceptions.APIException:
self._not_authenticated()
raise
#如果不为空,则列表类定义的之后的认证类都不会执行了,因为循环被return打断了
if user_auth_tuple is not None:
self._authenticator = authenticator
#self.user,self.auth解压赋值,user是私有属性,也就是方法被伪装为属性,实际调用了user的set方法,如果将当前用户返回给self.user,以后使用request._request.user就可以调用到当前用户对象了
'''
@user.setter
def user(self, value):
self._user = value
self._request.user = value
'''
self.user, self.auth = user_auth_tuple
return
self._not_authenticated()

drf认证功能的使用

1.在我们需要验证的类增加属性authentication_classes = [Auth,]
class Books(List, APIView):
authentication_classes = [Auth,]
2.定义我们的认证Auth类
from token_redis.models import User
from rest_framework.exceptions import ValidationError
from rest_framework.authentication import BaseAuthentication
class Auth(BaseAuthentication):
#必须定义authenticate方法和传入参数request
def authenticate(self,request):
token = request.query_params.get('token')
id = request.query_params.get('id')
if token:
ret = check_token(token,id)
if ret:
user = User.objects.filter(pk=id).first() return user,True
raise ValidationError('未登陆') 局部使用
在视图类中加一行:
authentication_classes = [Auth, ] 全局使用
在setting中配置
REST_FRAMEWORK={
"DEFAULT_AUTHENTICATION_CLASSES":["app01.myauth.Auth",]
}
局部禁用
在视图类中加一行:
authentication_classes = [ ]

drf 认证功能的更多相关文章

  1. django框架-DRF工程之认证功能

    1.在Rest framework中进行了一系列的封装,这个认证功能也是被封装到在DRF工程中的一种,想要使用,首先需要在配置文件中进行相应的配置 REST_FRAMEWORK = { ’DEFAUL ...

  2. python 全栈开发,Day97(Token 认证的来龙去脉,DRF认证,DRF权限,DRF节流)

    昨日内容回顾 1. 五个葫芦娃和三行代码 APIView(views.View) 1. 封装了Django的request - request.query_params --> 取URL中的参数 ...

  3. (四) DRF认证, 权限, 节流

    一.Token 认证的来龙去脉 摘要 Token 是在服务端产生的.如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端.前端可以在每次请求的时候带上 To ...

  4. drf认证组件、权限组件、jwt认证、签发、jwt框架使用

    目录 一.注册接口 urls.py views.py serializers.py 二.登录接口 三.用户中心接口(权限校验) urls.py views.py serializers.py 四.图书 ...

  5. ASP.NET Core 实现带认证功能的Web代理服务器

    引言 最近在公司开发了一个项目,项目部署架构图如下: 思路 如图中文本所述,公司大数据集群不允许直接访问外网,需要一个网关服务器代理请求,本处服务器A就是边缘代理服务器的作用. 通常技术人员最快捷的思 ...

  6. DRF认证组件流程分析

    视图函数中加上认证功能,流程见下图 import hashlib import time def get_random(name): md = hashlib.md5() md.update(byte ...

  7. DRF 认证、权限、限制

    DRF 认证.权限.限制   认证: 定义一个用户表和一个保存用户的Token表 # ======================day96======================= class ...

  8. yarn 用户导致的被挖矿 启用Kerberos认证功能,禁止匿名访问修改8088端口

    用户为dr.who,问下内部使用人员,都没有任务在跑: 结论: 恭喜你,你中毒了,攻击者利用Hadoop Yarn资源管理系统REST API未授权漏洞对服务器进行攻击,攻击者可以在未授权的情况下远程 ...

  9. 【DRF认证】

    目录 认证组件的详细用法 本文详细讲述了DRF认证组件的原理以及用法. @ * 源码剖析** 上一篇博客讲解DRF版本的时候我们都知道了,在dispatch方法里执行了initial方法来初始化我们的 ...

随机推荐

  1. codechef FIBTREE 码农题 线段树 树剖 标记永久化

    好烦啊,调了半天 线段树部分标记比较多,手抖打错了一个 剩下的都是取模的问题 我自己瞎jb推的公式里保留了abs,但是在模意义下是gg的,所以必须把正负区分开 调试的时候一定要注意构造各种形状的树,不 ...

  2. bzoj4650: [Noi2016]优秀的拆分 hash

    好气啊,没开longlong又biubiu了 底层: 用hash或者奇奇怪怪的算法兹磁logn求最长公共前后缀 思路: 统计出从一个点开始和结束的形如AA的子串的个数 统计的时候把相邻的结果相乘加起来 ...

  3. 练习三十二:用python实现:按相反的顺序输出列表的每一位值

    用python实现:按相反的顺序输出列表的每一位值 1. 使用list[::-1] list1 = ["one","two","three" ...

  4. 提升Java代码质量(一)

    博主双12入手了一本"Effective Java第二版",本系列文章将初步梳理书中内容,我也查了些资料,我会针对知识点做一点展开,方便以后复习回顾; Item1.考虑用静态工厂代 ...

  5. 微信小程序中的target和currentTarget区别

    最近在学习微信小程序相关知识,其中提到了两个属性target和currentTarget,其中target是指向触发事件的元素(常见于事件委托中),而currentTarget是指向捕获事件的元素(即 ...

  6. Python 中 创建类方法为什么要加self

    Python的类方法和普通的函数有一个明显的区别,在类的方法必须有一个额外的第一个参数(self),但在调用这个方法的时候不必为这个参数数值(显胜于隐的引发).在Python的类方法中这个特别的参数指 ...

  7. Web端 页面跳转 页面传值

    要把  Default.aspx 页面    TextBox1中的值    传值到   Default.aspx   Label上去 C#服务端跳转页面 Response    响应请求对象 Redi ...

  8. 对卷积(convolution)的理解

    参考文章 https://www.jianshu.com/p/daaaeb718aed https://blog.csdn.net/bitcarmanlee/article/details/54729 ...

  9. jQuery UI -- Repeater & 手风琴(Accordion)效果

    jQuery UI -- Repeater & 手风琴(Accordion)效果 很简单的范例,完全不用写程序 直接套用就能做! 但是,基础不稳的人,连「复制贴上」直接套用, 对您而言,都困难 ...

  10. HDU - 5096 ACM Rank (Treap)

    平衡树的题,Treap破之,比较难搞的出现相同题数罚时的情况,解决方法是在每个结点用一个set, 保证结点值的时候可以把题数和罚时保存到一个int里,令v = n*MaxPenaltySum-pena ...