DRF-Authention组件源码分析及扩展
drf 认证组件
1、认证组件源码执行流程
在该图中,我把与认证组件无关的代码都删除了,只留下了认证的代码,方便解析。每行注释的开头数字即代表了执行顺序


注意事项:
- 第5步中的self.authenticators获取流程:
- 首先,明确self代表的是request对象。则self.authenticators相当于去request对象中寻找authenticators的值。
- 其次,Request在实例化得到request对象时,在参数中可传入authenticators的值
- 通过下图流程分析:self.authenticators其实就是在视图类中定义的authentication_classes(也可在drf的配置中默认设置)


authentication_classes必须是一个列表(可迭代对象)
由于源码中指定了会执行authenticate方法,因此编写认证类时,认证函数名必须是authenticate,return时应该返回一个元组,且类需继承自BaseAuthentication
2. 实践:编写一个token认证类
假设token存储于数据库。另注意:实际工作中编写代码最好采用白名单模式。
class UnAuthentication(BaseAuthentication): # 默认继承BaseAuthentication
def authenticate(self, request): # 认证函数名固定为authenticate
# 获取token
token = request.query_params.get("token")
# 未传token
if not token:
return None
# 数据库不存在该token
user_object = models.UserInfo.objects.filter(token=token, status=1).first()
if not user_object:
return None
# token过期
if datetime.datetime.now() > user_object.token_expiry_date:
return None
return user_object, token # 认证成功,返回元组
3. 扩展点:
从认证失败后的执行过程中可发现:即使认证失败了程序也不会报错,且会继续执行后面的视图函数:
# --------认证失败----------
def _not_authenticated(self):
self._authenticator = None
if api_settings.UNAUTHENTICATED_USER:
self.user = api_settings.UNAUTHENTICATED_USER()
else:
self.user = None
if api_settings.UNAUTHENTICATED_TOKEN:
self.auth = api_settings.UNAUTHENTICATED_TOKEN()
else:
self.auth = None
那么第一个需求来了,如果我需要在认证失败后,立即让程序报错并停止执行后面的代码,该如何重写呢?
(仅供参考)答案:直接在认证失败后主动抛出错误即可:
class TokenAuthentication(BaseAuthentication):
def authenticate(self, request):
# 获取token
token = request.query_params.get("token")
# 未传token
if not token:
raise AuthenticationFailed({"code": return_code.AUTH_FAILED, "error": "认证失败,token不存在"})
# 数据库不存在该token
user_object = models.UserInfo.objects.filter(token=token, status=1).first()
if not user_object:
raise AuthenticationFailed({"code": return_code.AUTH_FAILED, "error": "认证失败123"})
# token过期
if datetime.datetime.now() > user_object.token_expiry_date:
raise AuthenticationFailed({"code": return_code.AUTH_OVERDUE, "error": "认证过期"})
return user_object, token
第二个需求:如果前端传token时不规范,有时在请求头里传,有时在查询参数中传....,那么该如何应用认证组件进行校验呢?
(仅供参考)答案:既然源码中对认证类列表进行循环了,则直接编写多个认证类即可(有多个认证类时,建议不要直接raise,否则可能导致后面的认证类无法校验)
class QueryParamsAuthentication(BaseAuthentication):
def authenticate(self, request):
# 判断token是否正确
# 1. 从查询参数获取token
token = request.query_params.get("token")
if not token:
return
# 2. 去数据库获取该token
user_obj = models.UserInfo.objects.filter(token=token).first()
# 有对象则认证成功,返回 request.user = 用户对象; request.auth = token
if user_obj:
return user_obj, token
return
def authenticate_header(self, request):
# return 'Basic realm="API"'
return "API"
class HeaderAuthentication(BaseAuthentication):
def authenticate(self, request):
# 判断token是否正确
# 1. 从请求头获取token
token = request.META.get("HTTP_AUTHORIZATION")
if not token:
return
# 2. 去数据库获取该token
user_obj = models.UserInfo.objects.filter(token=token).first()
# 有对象则认证成功,返回user和auth
if user_obj:
return user_obj, token
return
def authenticate_header(self, request):
# return 'Basic realm="API"'
return "API"
如果有多个认证类,则建议在最后一个认证类中默认抛出错误即可
class QueryParamsAuthentication(BaseAuthentication):
def authenticate(self, request):
# 判断token是否正确
# 1. 从查询参数获取token
token = request.query_params.get("token")
if not token:
return
# 2. 去数据库获取该token
user_obj = models.UserInfo.objects.filter(token=token).first()
# 有对象则认证成功,返回 request.user = 用户对象; request.auth = token
if user_obj:
return user_obj, token
return
def authenticate_header(self, request):
# return 'Basic realm="API"'
return "API"
class HeaderAuthentication(BaseAuthentication):
def authenticate(self, request):
# 判断token是否正确
# 1. 从请求头获取token
token = request.META.get("HTTP_AUTHORIZATION")
if not token:
return
# 2. 去数据库获取该token
user_obj = models.UserInfo.objects.filter(token=token).first()
# 有对象则认证成功,返回user和auth
if user_obj:
return user_obj, token
return
def authenticate_header(self, request):
# return 'Basic realm="API"'
return "API"
class NoAuthentication(BaseAuthentication):
def authenticate(self, request):
raise AuthenticationFailed({"code": 10001, "detail": "认证失败"})
DRF-Authention组件源码分析及扩展的更多相关文章
- Django框架之DRF 认证组件源码分析、权限组件源码分析、频率组件源码分析
认证组件 权限组件 频率组件
- DRF的认证组件(源码分析)
DRF认证组件(源码分析) 1. 数据库建立用户表 在drf中也给我们提供了 认证组件 ,帮助我们快速实现认证相关的功能,例如: # models.py from django.db import m ...
- Django框架之drf:8、断点调试,权限、认证、频率组件源码分析,基于APIView编写分页,异常处理
Django框架之drf 一.断点调式使用 指,在我们编写代码的时候,程序运行出现报错是无可避免的,当程序 出现报错时,我们需要找到出现报错的代码进行修改,如果时简短的代码很容易就可以找到报错位置 ...
- DRF的限流组件(源码分析)
DRF限流组件(源码分析) 限流,限制用户访问频率,例如:用户1分钟最多访问100次 或者 短信验证码一天每天可以发送50次, 防止盗刷. 对于匿名用户,使用用户IP作为唯一标识. 对于登录用户,使用 ...
- DRF的Serializer组件(源码分析)
DRF的Serializer组件(源码分析) 1. 数据校验 drf中为我们提供了Serializer,他主要有两大功能: 对请求数据校验(底层调用Django的Form和ModelForm) 对数据 ...
- ceph-csi组件源码分析(1)-组件介绍与部署yaml分析
更多ceph-csi其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 ceph-csi组件源码分析(1)-组件介绍与部署yaml分析 基于tag v3.0.0 ht ...
- 开源MyBatisGenerator组件源码分析
开源MyBatisGenerator组件源码分析 看源码前,先了解Generator能做什么? MyBatisGenerator是用来生成mybatis的Mapper接口和xml文件的工具,提供多种启 ...
- Django-restframework 源码之认证组件源码分析
Django-restframework 源码之认证组件源码分析 一 前言 之前在 Django-restframework 的流程分析博客中,把最重要的关于认证.权限和频率的方法找到了.该方法是 A ...
- element-ui 组件源码分析整理笔记目录
element-ui button组件 radio组件源码分析整理笔记(一) element-ui switch组件源码分析整理笔记(二) element-ui inputNumber.Card .B ...
- Android base-adapter-helper 源码分析与扩展
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/44014941,本文出自:[张鸿洋的博客] 本篇博客是我加入Android 开源项 ...
随机推荐
- php curl访问https 域名接口一直报错的问题
这两天一直在对接一个https的接口 通过本地postman完美链接后再服务器一直报错 出现问题:linux 下 curl可以正常访问 但是PHP请求一直返回false 测试方法:var_dump(c ...
- 想不到WhaleStudio和Talend的差异竟如此之大!
最近我们遇到很多客户需求是把Talend迁移到WhaleStudio,主要是发现WhaleStudio支持的数据源多很多,从各个版本的SAP到AWS Redshift,S3,从MangoDB CDC到 ...
- ρars/ey 题解
给个链接:ρars/ey. 我们考虑一个树上背包. 设 \(f_{u,i}\) 表示在 \(u\) 号节点的子树内删除 \(i\) 个点的最小代价.显然有答案为 \(f_{1,siz_1-1}\). ...
- 暑假Java自学进度总结05
一.今日所学: 1.if的第一个表达式: if(关系表达式){ 语句: } 执行流程: 1>首先执行关系表达式的值 2>如果关系表达式的值为true则执行语句,否则不执行 3>继续执 ...
- 推荐5款免费、开箱即用的Vue后台管理系统模板
前言 在现今的软件开发领域,Vue凭借其高效.灵活和易于上手的特性,成为了前端开发的热门选择.对于需要快速搭建企业级后台管理系统的开发者而言,使用现成的Vue后台管理系统模板无疑是一个明智之举.本文大 ...
- k8s获取集群内所有在使用镜像
kubectl get pods --all-namespaces -o jsonpath="{..image}" | tr -s '[[:space:]]' ' ' | sort ...
- Python if __name__ == "__main__" 解释
一种机制,允许脚本以不同的方式运行,这取决于作为独立的程序执行还是作为模块被其他脚本导入.这种机制就是 if __name == "__main__" 其作用是控制某些代码块只在该 ...
- 国产化适配——人大金仓V8R6(1)
本文主要记录kingbase安装及存储过程修改相关内容,或有错漏,请指正. 原数据库:Mysql8.0.31 现数据库:KingbaseES V008R006C008M001B0030 on x86_ ...
- 全网最适合入门的面向对象编程教程:45 Python 实现常见数据结构-链表、树、哈希表、图和堆
全网最适合入门的面向对象编程教程:45 Python 实现常见数据结构-链表.树.哈希表.图和堆 摘要: 数据结构是计算机科学中的一种组织和存储数据的方式,它决定了数据的访问方式和操作效率,数据结构的 ...
- 使用 Dependify 工具探索 .NET 应用程序依赖项
在大型项目中,由于各种组件的复杂性和互连性,管理依赖项可能变得具有挑战性.如果没有适当的工具或文档,可能很难浏览项目并对依赖项做出假设.以下是在大型项目中难以导航项目依赖项的几个原因: 复杂性:大型项 ...