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. 优化MyEclipse编译速度慢的问题

    转载大神的 https://www.cnblogs.com/luxd/p/5999217.html

  2. net core 认证及简单集群

    net core 认证及简单集群 在Asp.net WebAPI中,认证是通过AuthenticationFilter过滤器实现的,我们通常的做法是自定义AuthenticationFilter,实现 ...

  3. (转)linux dumpe2fs命令

    linux dumpe2fs命令 命令名称 dumpe2fs - 显示ext2/ext3/ext4文件系统信息. dumpe2fs命令语法 dumpe2fs [ -bfhixV ] [ -o supe ...

  4. Unbuntu 自动重启MySQL

    上个月,通过Unbuntu搭建了WordPress,一切运行良好. UBUNTU搭建WORDPRESS-MYSQL-APACHE 但是,最近几天,不知道啥情况,MySQL偶尔会出现Stop:影响了bl ...

  5. Spark Mllib里决策树回归分析如何对numClasses无控制和将部分参数设置为variance(图文详解)

    不多说,直接上干货! 在决策树二元或决策树多元分类参数设置中: 使用DecisionTree.trainClassifier   见 Spark Mllib里如何对决策树二元分类和决策树多元分类的分类 ...

  6. zip (ICSharpCode.SharpZipLib.dll文件需要下载)

    ZipClass zc=new ZipClass (); zc.ZipDir(@"E:\1\新建文件夹", @"E:\1\新建文件夹.zip", 1);//压缩 ...

  7. python-day1作业(感谢视频老师留的作业)

    __author__ = 'zht' #!/usr/bin/env python # -*- coding: utf-8 -*- ''' #努力学习每一天 ''' #尝试次数计数器 tries = 0 ...

  8. SequenceFile和MapFile

    HDFS和MR主要针对大数据文件来设计,在小文件处理上效率低.解决方法是选择一个容器,将这些小文件包装起来,将整个文件作为一条记录,可以获取更高效率的储存和处理,避免多次打开关闭流耗费计算资源.hdf ...

  9. Python3+Selenium3+webdriver学习笔记14(等待判断 鼠标事件 )

    !/usr/bin/env python -*- coding:utf-8 -*-'''Selenium3+webdriver学习笔记14(等待判断 鼠标事件 )'''from selenium im ...

  10. SQL Server 查询性能优化——创建索引原则

    索引是什么?索引是提高查询性能的一个重要工具,索引就是把查询语句所需要的少量数据添加到索引分页中,这样访问数据时只要访问少数索引的分页就可以.但是索引对于提高查询性能也不是万能的,也不是建立越多的索引 ...