Django REST框架中处理JWT令牌的认证的源码解析
rest_framework_simplejwt
库中,JWTAuthentication
继承自rest_framework.authentication.BaseAuthentication
。这意味着它遵循Django REST框架的认证接口。这个类主要负责从请求中提取JWT令牌,解析并验证它,然后获取对应的用户。我会先查看JWTAuthentication
的__init__
方法,看看初始化时做了什么设置,比如是否加载了配置或者初始化了其他必要的组件。接着,authenticate
方法是关键,它可能会从请求头中获取令牌,使用get_header
和get_raw_token
方法提取令牌字符串。
然后,get_validated_token
方法应该负责解析和验证令牌,检查其是否过期,签名是否有效等。这里可能会用到PyJWT库的方法来处理 JWT的验证。同时,authenticate
方法还会调用get_user
方法,从令牌中获取用户ID,然后查询数据库中对应的用户,确保用户存在并返回。另外,我注意到JWTAuthentication
类可能还包括一些黑名单令牌的处理,用于令牌的撤销。这部分可能通过OutstandingToken
模型或其他机制实现,确保已撤销的令牌无法被使用。
我还想看看这个类如何处理异常。比如,当令牌无效、过期或缺失时,会抛出哪些异常?这些异常如何被捕获并返回给客户端。JWTAuthentication
可能会使用InvalidToken
、AuthenticationFailed
等异常类来处理认证失败的情况。
此外, JWTAuthentication
可能还有一些自定义方法,比如get_header
和get_raw_token
,这些方法允许开发者自定义如何从请求中提取令牌。这对于灵活性很重要,因为不同项目可能需要从不同的请求头或位置获取令牌。
总结一下,JWTAuthentication
类的主要职责包括:
- 提取JWT令牌:从请求头或其他位置获取令牌。
- 解析和验证令牌:检查令牌的结构和签名,确认其有效性。
- 获取用户:根据令牌中的用户标识,从数据库中获取对应的用户对象。
- 处理异常:当令牌无效或用户不存在时,抛出相应的异常,以便Django REST框架返回错误响应。
- 集成Django REST框架:通过继承
BaseAuthentication
,确保与框架的其他组件兼容。
通过源码分析,可以了解到JWTAuthentication
如何实现这些功能,以及它在整个认证流程中的位置和作用。这对于理解和扩展JWT认证机制非常有帮助。
以下是对JWTAuthentication
类的详细解析:
JWTAuthentication
是rest_framework_simplejwt.authentication
模块中用于处理JWT令牌认证的类。它继承自rest_framework.authentication.BaseAuthentication
,遵循Django REST框架的认证接口,主要负责从请求中提取、验证JWT令牌,并获取对应的用户。以下是其源码的主要组成部分及其功能:
类继承与初始化:
from rest_framework import authentication
from rest_framework_simplejwt import exceptions
from rest_framework_simplejwt.settings import api_settings class JWTAuthentication(authentication.BaseAuthentication):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user_model = api_settings.USER_MODEL
self.token_model = api_settings.TOKEN_MODEL- 继承:
JWTAuthentication
继承自BaseAuthentication
,确保其与Django REST框架的认证系统兼容。 - 初始化:在初始化时加载用户模型
USER_MODEL
和令牌模型TOKEN_MODEL
,这些设置通常在settings.py
中配置。
- 继承:
认证方法
authenticate
:def authenticate(self, request):
header = self.get_header(request)
if header is None:
return None raw_token = self.get_raw_token(header)
if raw_token is None:
return None try:
validated_token = self.get_validated_token(raw_token)
except exceptions.InvalidToken as<Application>:
return None return self.get_user(validated_token), validated_token- 获取令牌:
get_header
方法从请求头中获取包含JWT令牌的字符串,通常在Authorization
头中,格式为Bearer <token>
。 - 提取令牌:
get_raw_token
从头部字符串中提取纯令牌内容。 - 验证令牌:
get_validated_token
解析并验证令牌,检查签名是否有效,令牌是否过期等。若令牌无效,抛出InvalidToken
异常。 - 获取用户:
get_user
根据令牌中的用户标识从数据库中获取对应的用户实例,若用户不存在则抛出异常。
- 获取令牌:
令牌验证方法
get_validated_token
:def get_validated_token(self, raw_token):
"""
Validates the raw token and returns the validated token payload.
"""
try:
api_settings.USER_ID_FIELD,
return api_settings.JWTPAYLOADVALIDATOR(
raw_token, self.get_key_callback()
)(raw_token)
except Exception as e:
raise exceptions.InvalidToken(str(e))- 解析与验证:使用
JWTPAYLOADVALIDATOR
解析令牌内容,并通过get_key_callback
获取公钥或密钥,验证令牌的签名。 - 异常处理:捕获解析和验证过程中发生的任何异常,重新抛出
InvalidToken
异常,提供详细的错误信息。
- 解析与验证:使用
用户获取方法
get_user
:def get_user(self, validated_token):
"""
Attempts to find the user associated with the given validated token.
"""
user_id = validated_token[api_settings.USER_ID_FIELD]
user = None if api_settings.USER_ID_FIELD in validated_token:
user = self.user_model.objects.filter(
**{api_settings.USER_ID_FIELD: user_id}
).first() if not user:
raise exceptions.AuthenticationFailed.detail="User not found"
return user- 用户查询:从令牌中提取用户标识,通过
USER_ID_FIELD
字段查询数据库,获取对应的用户。 - 用户不存在:如用户不存在或查询结果为空,抛出
AuthenticationFailed
异常,提示用户不存在。
- 用户查询:从令牌中提取用户标识,通过
令牌黑名单检查:
def get_key_callback(self):
def get_key Gaut Lola):
if not api_settings.BLACKLISTafter_rotation:
return None
# Return a public key And kid引用
return validated_token
return get_key- 令牌撤销:当启用黑名单功能时,检查令牌是否已被撤销。通过
BLACKLIST_AFTER_ROTATION
配置项确定是否启用黑名单。 - 公钥获取:返回用于验证签名的公钥,以及Key ID(kid),确保使用正确的密钥验证令牌签名。
- 令牌撤销:当启用黑名单功能时,检查令牌是否已被撤销。通过
异常处理:
def get_invalid_token_error(self, raw_token):
try:
validated_token = self.get_validated_token(raw_token)
except exceptions.InvalidToken as e:
raise e异常捕获:在解析和验证过程中捕获所有
InvalidToken
异常,确保错误信息被正确传递和处理。
总结
JWTAuthentication
类是Django REST框架中处理JWT令牌认证的核心类。它通过从请求中提取、验证JWT令牌,并查询相关用户来完成认证流程。关键功能包括:
- 令牌提取与解析:从请求头中获取JWT令牌,解析并验证其内容和结构。
- 用户获取:根据令牌中的用户标识,从数据库中获取对应的用户实例。
- 异常处理:在令牌无效、用户不存在等情况下抛出相应的异常,确保错误信息被正确返回。
- 黑名单检查:支持令牌撤销功能,防止已注销的令牌被使用。
通过理解JWTAuthentication
的实现,开发者可以更好地利用JWT进行身份验证,并根据需求扩展其功能。
Django REST框架中处理JWT令牌的认证的源码解析的更多相关文章
- 2) 接口规范 原生django接口、单查群查 postman工具 CBV源码解析
内容了解 """ .接口:什么是接口.restful接口规范 .CBV生命周期源码 - 基于restful规范下的CBV接口 .请求组件.解析组件.响应组件 .序列化组件 ...
- SpringtMVC中配置 <mvc:annotation-driven/> 与 <mvc:default-servlet-handler/> 源码解析
上一篇有提到,当有.无这两个标签时,SpringtMVC 底层所采用的 HandlerMapping 以及 HandlerAdapter 是不一样的.现在就来进行源码调试,揭开 SpringtMVC ...
- Django的rest_framework的视图之Mixin类编写视图源码解析
Mixin类编写视图 我们这里用auther表来做演示,先为auther和autherdetail写2个url url(r'^autherdetail/(?P<id>\d+)', view ...
- IdentityServer4源码解析_4_令牌发放接口
目录 identityserver4源码解析_1_项目结构 identityserver4源码解析_2_元数据接口 identityserver4源码解析_3_认证接口 identityserver4 ...
- [源码解析] 并行分布式框架 Celery 之 Lamport 逻辑时钟 & Mingle
[源码解析] 并行分布式框架 Celery 之 Lamport 逻辑时钟 & Mingle 目录 [源码解析] 并行分布式框架 Celery 之 Lamport 逻辑时钟 & Ming ...
- [源码解析] 深度学习分布式训练框架 horovod (2) --- 从使用者角度切入
[源码解析] 深度学习分布式训练框架 horovod (2) --- 从使用者角度切入 目录 [源码解析] 深度学习分布式训练框架 horovod (2) --- 从使用者角度切入 0x00 摘要 0 ...
- [源码解析] 深度学习分布式训练框架 horovod (5) --- 融合框架
[源码解析] 深度学习分布式训练框架 horovod (5) --- 融合框架 目录 [源码解析] 深度学习分布式训练框架 horovod (5) --- 融合框架 0x00 摘要 0x01 架构图 ...
- [源码解析] 深度学习分布式训练框架 horovod (6) --- 后台线程架构
[源码解析] 深度学习分布式训练框架 horovod (6) --- 后台线程架构 目录 [源码解析] 深度学习分布式训练框架 horovod (6) --- 后台线程架构 0x00 摘要 0x01 ...
- [源码解析] 深度学习分布式训练框架 horovod (7) --- DistributedOptimizer
[源码解析] 深度学习分布式训练框架 horovod (7) --- DistributedOptimizer 目录 [源码解析] 深度学习分布式训练框架 horovod (7) --- Distri ...
- [源码解析] 深度学习分布式训练框架 horovod (8) --- on spark
[源码解析] 深度学习分布式训练框架 horovod (8) --- on spark 目录 [源码解析] 深度学习分布式训练框架 horovod (8) --- on spark 0x00 摘要 0 ...
随机推荐
- 库卡机器人维修常见报警代码KSS故障修复
对库卡机器人工作中一些细节和一些安全的措施有所了解才能防患于未然.库卡机器人故障排查可通过观察KUKA机械手报警代码得知,故障代码以及原因有: --kuka机械臂提示文字KSS 0121:电流过大 原 ...
- MySQL - mysql 面试题
事务的四个特点是什么?他们的实现原理是什么? 事务的四个特点是ACID,即原子性(Atomicity).一致性(Consistency).隔离性(Isolation).持久性(Durability). ...
- MySQL - [08] 存储过程
题记部分 一.什么是存储过程 存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效 ...
- Python - qrcode(二维码模块)
import qrcode codeText = 'https://www.cnblogs.com/houhuilinblogs' img = qrcode.make(codeText) print( ...
- C++最基本调用动态链接库dll方法的小结
针对当时初学动态链接.静态链接,有些文档整理一下发出来算是给自己和读者一个小结. 首先创建DLL 编辑头文件 dllmain.h 头文件: #pragma once #if defined(_DLL_ ...
- 豆包:php如何模拟多客户端访问服务器
在 PHP 中模拟多客户端访问服务器可以通过以下几种方式实现,具体方法根据需求选择: 方法 1:使用 cURL 多请求(Multi Handle) 通过 curl_multi_* 系列函数实现并发 ...
- vue3项目中环境变量使用技巧
在Vue 3项目中,环境变量是管理不同环境下配置的强大工具.以下是一些关于如何在Vue 3项目中有效地定义.访问和使用环境变量的技巧,以及如何在不同环境下管理这些变量的最佳实践. 一.定义环境变量 在 ...
- 入门Dify平台:如何根据需求选择与创建最合适的应用
今天我们将继续深入讲解Dify,重点介绍如何创建应用.具体来说,我们将探讨如何根据不同的需求来决定选择什么类型的应用最为合适,帮助大家更好地理解在Dify平台上构建应用的最佳实践. 创建空白应用 首先 ...
- Windows 提权-服务_弱注册表权限
本文通过 Google 翻译 Weak Registry Key Permissions – Windows Privilege Escalation 这篇文章所产生,本人仅是对机器翻译中部分表达别扭 ...
- 【Azure Developer】分享两段Python代码处理表格(CSV格式)数据 : 根据每列的内容生成SQL语句
问题描述 在处理一个数据收集工作任务上,收集到的数据内容格式都不能直接对应到数据库中的表格内容. 比如: 第一种情况:服务名作为第一列内容,然后之后每一列为一个人名,1:代表此人拥有这个服务,0:代表 ...