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. 《从0到1学习Flink》—— 如何自定义 Data Source ?

    前言 在 <从0到1学习Flink>-- Data Source 介绍 文章中,我给大家介绍了 Flink Data Source 以及简短的介绍了一下自定义 Data Source,这篇 ...

  2. 重写FileUpload控件让它可以显示上传后的文件名

    我在以前的开发中经常遇到这样的场景:文件上传之后需要显示文件名,但是asp.net自带的fileupload是不能付给上传后的文件名值的. 以前都是做一个label显示的,今天想起来了,写个控件封装一 ...

  3. 通用的ashx调用

    直接上代码 还是有一定通用性的 <%@ WebHandler Language="C#" Class="MyService" %> using Sy ...

  4. vue学习之路之需要了解的知识汇总

    一.vue是什么? 相关网页:  https://vuejs.bootcss.com/v2/guide/       及菜鸟教程       https://www.runoob.com/vue2/v ...

  5. To the world you may be one person, but to one person you may be the world.

    To the world you may be one person, but to one person you may be the world.对于世界而言,你是一个人:但对于某人而言,你是他的 ...

  6. mui对话框、表单

    1.mui.alert() 普通提醒参数 1.message Type: String 提示对话框上显示的内容 2.title Type: String 提示对话框上显示的标题 3.btnValue ...

  7. php 判断字符串中是否包含另一个字符串 strpos

    strpos (PHP 4, PHP 5, PHP 7) strpos — 查找字符串首次出现的位置 说明 strpos ( string $haystack ,  $needle [, int $o ...

  8. apple-touch-icon-precomposed

    <link rel="apple-touch-icon-precomposed" href=""> apple-touch-icon-precomp ...

  9. SQL Server 2016,2014 “无法找到数据库引擎启动句柄”

    当我决定安装SharePoint 2016 IT预览版时,我想我应该将它安装在Windows Server 2016技术预览版以及SQL Server 2016社区技术预览版(CTP)上.我敢打赌,你 ...

  10. html 之table标签结构学习

    一.HTML table标签结构 html 中table标签的结构情况,如下所示: <!-- table标签结构如下: <table> <thead> # thead表格 ...