drf 认证组件

1、认证组件源码执行流程

在该图中,我把与认证组件无关的代码都删除了,只留下了认证的代码,方便解析。每行注释的开头数字即代表了执行顺序



注意事项:
  1. 第5步中的self.authenticators获取流程:

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

  1. authentication_classes必须是一个列表(可迭代对象)

  2. 由于源码中指定了会执行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组件源码分析及扩展的更多相关文章

  1. Django框架之DRF 认证组件源码分析、权限组件源码分析、频率组件源码分析

    认证组件 权限组件 频率组件

  2. DRF的认证组件(源码分析)

    DRF认证组件(源码分析) 1. 数据库建立用户表 在drf中也给我们提供了 认证组件 ,帮助我们快速实现认证相关的功能,例如: # models.py from django.db import m ...

  3. Django框架之drf:8、断点调试,权限、认证、频率组件源码分析,基于APIView编写分页,异常处理

    Django框架之drf 一.断点调式使用 ​ 指,在我们编写代码的时候,程序运行出现报错是无可避免的,当程序 出现报错时,我们需要找到出现报错的代码进行修改,如果时简短的代码很容易就可以找到报错位置 ...

  4. DRF的限流组件(源码分析)

    DRF限流组件(源码分析) 限流,限制用户访问频率,例如:用户1分钟最多访问100次 或者 短信验证码一天每天可以发送50次, 防止盗刷. 对于匿名用户,使用用户IP作为唯一标识. 对于登录用户,使用 ...

  5. DRF的Serializer组件(源码分析)

    DRF的Serializer组件(源码分析) 1. 数据校验 drf中为我们提供了Serializer,他主要有两大功能: 对请求数据校验(底层调用Django的Form和ModelForm) 对数据 ...

  6. ceph-csi组件源码分析(1)-组件介绍与部署yaml分析

    更多ceph-csi其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 ceph-csi组件源码分析(1)-组件介绍与部署yaml分析 基于tag v3.0.0 ht ...

  7. 开源MyBatisGenerator组件源码分析

    开源MyBatisGenerator组件源码分析 看源码前,先了解Generator能做什么? MyBatisGenerator是用来生成mybatis的Mapper接口和xml文件的工具,提供多种启 ...

  8. Django-restframework 源码之认证组件源码分析

    Django-restframework 源码之认证组件源码分析 一 前言 之前在 Django-restframework 的流程分析博客中,把最重要的关于认证.权限和频率的方法找到了.该方法是 A ...

  9. element-ui 组件源码分析整理笔记目录

    element-ui button组件 radio组件源码分析整理笔记(一) element-ui switch组件源码分析整理笔记(二) element-ui inputNumber.Card .B ...

  10. Android base-adapter-helper 源码分析与扩展

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/44014941,本文出自:[张鸿洋的博客] 本篇博客是我加入Android 开源项 ...

随机推荐

  1. hibernate validation,spring validation自定义参数校验

    1.背景 在实际开发中,我们除了会使用常用的参数判断,如字符串不为空,最大值,最小值等 我们还可以自定义参数校验规则 2.实际生产问题 实际生产中同步订单的时候, 假设我们要求订单状态值只能是 -1, ...

  2. 推荐一款界面优雅、功能强大的 .NET + Vue 权限管理系统

    前言 今天推荐一款用 .NET 和 Vue3 实现的开源权限管理系统.它的界面清爽干净,功能强大,还具备灵活的角色权限分配功能,能够满足不同规模企业的管理需求.无论你是开发新手还是大神,都能轻松上手, ...

  3. 运用Npcap库实现SYN半开放扫描

    Npcap 是一款高性能的网络捕获和数据包分析库,作为 Nmap 项目的一部分,Npcap 可用于捕获.发送和分析网络数据包.本章将介绍如何使用 Npcap 库来实现半开放扫描功能.TCP SYN 半 ...

  4. [学习笔记] MST(最小生成树) - 图论

    [学习笔记] MST(最小生成树) - 图论 MST,最小生成树,一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边.--百度百科 对于 ...

  5. CH08_结构体

    CH08_结构体 基本概念 结构体属于用户自定义数据类型,允许用户存储不同的数据类型. 定义和使用 语法:struct 结构体名{ 结构体成员列表} 通过结构体创建变量的方式有三种: struct 结 ...

  6. 一次生产环境mysql迁移操作(二)mysql空间释放(碎片整理)

    一次生产环境mysql迁移操作(一)数据归档 一次生产环境mysql迁移操作(二)mysql空间释放(碎片整理) 上文中增加了定时归档,现在一些大表磁盘空间一直不释放,导致数据库文件越来越大.现在介绍 ...

  7. C语言编程-GCC编译过程

    gcc编译 预处理 ->编译->汇编->链接 预处理 gcc -E helloworld.c -o helloworld.i 头文件展开:不检查语法错误,即可以展开任意文件: 宏定义 ...

  8. 【Python自动化】之利用JS操作页面滚动条(新)

    如何操作页面中的滚动条,有以下几个方法: 一.查找可见元素进行滚动页面(通用) 方法一: ①移动到元素element对象的"顶端",与当前窗口的"顶部"对齐(默 ...

  9. 【测试平台开发】——06Flask后端api开发实战(三)——API接口关联数据库

    本章节演示如何创建接口服务,用接口关联数据库数据,包括get请求和post请求. 一.Flask-RESTful插件 restful api是用于在前端与后台进行通信的一套规范.使用这个规范可以让前后 ...

  10. Error:java: JDK isn't specified for module

    报错: Error:java: JDK isn't specified for module 背景: 删除原项目文件夹内所有文件,copy的新的配置文件与src文件夹等,期间打开该项目的IDEA一直处 ...