在 Python 3 中,Django 的 APIView 类是 Django REST Framework(DRF)中用于构建 API 视图的核心基类。它提供了一个灵活的框架来处理 HTTP 请求,并通过一系列方法支持认证、权限检查和请求限制等功能。

在这里插入图片描述

  • self.perform_authentication(request):认证
  • self.check_permissions(request) :权限验证
  • self.check_throttles(request) :请求速率限制

1. self.perform_authentication(request)

作用

self.perform_authentication(request) 用于对传入的 HTTP 请求进行身份认证(authentication)。它的主要目的是验证请求是否来自合法用户,并将认证后的用户信息(如用户对象)绑定到 request.userrequest.auth 属性上。

  • request.user: 通常存储认证后的用户对象(例如 Django 的 User 模型实例)。如果未认证,默认为 AnonymousUser
  • request.auth: 存储认证过程中可能附加的认证信息,例如 JWT 令牌、OAuth 令牌等。
实现原理

perform_authentication 方法调用了 DRF 的认证流程,依赖于 authentication_classes 属性中定义的认证类。DRF 的认证机制是模块化的,允许开发者通过配置不同的认证类(如 SessionAuthenticationTokenAuthenticationJWTAuthentication 等)来支持多种认证方式。

APIView 类中,perform_authentication 的定义如下(参考 DRF 源码,基于 3.15 版本):

def perform_authentication(self, request):request.user

看似简单,但实际逻辑隐藏在 request.user 的属性访问中。当访问 request.user 时,DRF 会触发以下步骤:

  1. 获取认证类:从 self.authentication_classes 获取配置的认证类列表。这些类继承自 rest_framework.authentication.BaseAuthentication
  2. 逐个调用认证类:按顺序调用每个认证类的 authenticate 方法,尝试对请求进行认证。
    • 每个 authenticate 方法返回一个 (user, auth) 元组,表示认证成功;如果返回 None,则尝试下一个认证类。
    • 如果认证失败且认证类抛出 AuthenticationFailed 异常,DRF 会立即返回 401 Unauthorized 响应。
  3. 设置认证结果
    • 如果认证成功,request.user 被设置为认证后的用户对象,request.auth 被设置为认证令牌或其他上下文信息。
    • 如果没有认证类成功认证,request.user 默认为 AnonymousUserrequest.authNone
执行时机

perform_authenticationAPIViewinitial 方法中被调用,initial 方法是请求处理流程的初始化阶段:

def initial(self, request, *args, **kwargs):self.perform_authentication(request)self.check_permissions(request)self.check_throttles(request)# 其他初始化逻辑
配置认证类

APIView 子类中,可以通过 authentication_classes 属性指定认证方式。例如:

from rest_framework.views import APIView
from rest_framework.authentication import SessionAuthentication, TokenAuthenticationclass MyAPIView(APIView):authentication_classes = [SessionAuthentication, TokenAuthentication]def get(self, request):return Response({"user": request.user.username})

在上述例子中,DRF 会优先尝试 SessionAuthentication,如果失败则尝试 TokenAuthentication

注意事项
  • 短路行为perform_authentication 不会直接抛出异常,而是依赖认证类的实现。如果所有认证类都返回 None,请求被视为匿名请求。
  • 性能考虑:认证可能涉及数据库查询(如验证用户令牌),因此应尽量优化认证类的实现,避免不必要的性能开销。
  • 自定义认证:可以继承 BaseAuthentication 创建自定义认证类,并添加到 authentication_classes 中。例如:
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailedclass CustomAuth(BaseAuthentication):def authenticate(self, request):auth_header = request.headers.get('Authorization')if not auth_header:return None# 自定义认证逻辑user = validate_token(auth_header)  # 假设的 token 验证函数if not user:raise AuthenticationFailed('Invalid token')return (user, auth_header)
常见使用场景
  • 基于令牌的认证:如 TokenAuthentication 或 JWT,用于移动端或单页应用。
  • 会话认证:如 SessionAuthentication,适用于基于浏览器的应用。
  • 匿名访问:允许匿名用户访问某些 API(request.userAnonymousUser)。

2. self.check_permissions(request)

作用

self.check_permissions(request) 用于检查请求用户是否具有执行当前操作的权限。它基于 permission_classes 属性中定义的权限类,决定是否允许请求继续处理。如果权限检查失败,DRF 会抛出 PermissionDenied 异常,导致返回 403 Forbidden 响应。

实现原理

check_permissions 方法会遍历 self.permission_classes 中定义的权限类,调用每个权限类的 has_permission 方法:

def check_permissions(self, request):for permission in self.get_permissions():if not permission.has_permission(request, self):self.permission_denied(request, message=getattr(permission, 'message', None))
  • 权限类:每个权限类继承自 rest_framework.permissions.BasePermission,并实现 has_permission 方法(对于对象级权限,还可能实现 has_object_permission)。
  • 检查逻辑has_permission 方法返回 True 表示权限通过,False 表示拒绝。如果任何一个权限类返回 False,DRF 会抛出 PermissionDenied 异常。
  • 错误处理permission_denied 方法会生成 403 响应,并包含权限类提供的错误信息(如果有)。
执行时机

check_permissionsinitial 方法中,在 perform_authentication 之后调用。这是因为权限检查通常依赖于认证结果(例如,检查 request.user 是否有特定权限)。

配置权限类

可以通过 permission_classes 属性指定权限。例如:

from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated, IsAdminUserclass MyAPIView(APIView):permission_classes = [IsAuthenticated, IsAdminUser]def get(self, request):return Response({"message": "You have admin access"})

在上述例子中,用户必须同时通过 IsAuthenticated(已登录)和 IsAdminUser(管理员权限)检查才能访问 API。

内置权限类

DRF 提供了一些常用的权限类:

  • AllowAny: 允许所有用户(包括匿名用户)访问。
  • IsAuthenticated: 仅允许已认证用户访问。
  • IsAdminUser: 仅允许管理员用户访问。
  • IsAuthenticatedOrReadOnly: 允许匿名用户的只读访问(GET、HEAD、OPTIONS),但写操作需要认证。
自定义权限

可以创建自定义权限类。例如,限制只有特定角色的用户可以访问:

from rest_framework.permissions import BasePermissionclass IsPremiumUser(BasePermission):def has_permission(self, request, view):return request.user.is_authenticated and request.user.is_premium
注意事项
  • 权限顺序:权限类按顺序检查,建议将更严格的权限放在前面以提高效率。
  • 对象级权限:对于需要检查特定对象的权限(如编辑某个资源),可以在视图中调用 self.check_object_permissions(request, obj),触发权限类的 has_object_permission 方法。
  • 错误信息:可以通过权限类的 message 属性自定义错误提示。例如:
class IsPremiumUser(BasePermission):message = "You must be a premium user to access this resource."def has_permission(self, request, view):return request.user.is_authenticated and request.user.is_premium
常见使用场景
  • 限制访问:仅允许认证用户或特定角色(如管理员、订阅者)访问 API。
  • 只读访问:允许匿名用户读取数据,但限制写操作。
  • 动态权限:根据请求方法(GET、POST 等)或资源类型动态调整权限。

3. self.check_throttles(request)

作用

self.check_throttles(request) 用于限制请求速率(rate limiting),防止 API 被滥用。它基于 throttle_classes 属性中定义的限制类,检查用户或 IP 的请求频率是否超出限制。如果超出限制,DRF 会抛出 Throttled 异常,导致返回 429 Too Many Requests 响应。

实现原理

check_throttles 方法会遍历 self.throttle_classes 中定义的限制类,调用每个限制类的 allow_request 方法:

def check_throttles(self, request):for throttle in self.get_throttles():if not throttle.allow_request(request, self):self.throttled(request, throttle.wait())
  • 限制类:每个限制类继承自 rest_framework.throttling.BaseThrottle,并实现 allow_request 方法,决定是否允许当前请求。
  • 检查逻辑allow_request 返回 True 表示请求允许,False 表示请求被限制。如果被限制,throttle.wait() 返回预计的等待时间(秒),并包含在 429 响应中。
  • 缓存支持:DRF 的限制机制通常依赖缓存(如 Redis 或 Django 的内存缓存)来跟踪请求频率。
执行时机

check_throttlesinitial 方法中,在 perform_authenticationcheck_permissions 之后调用。这是因为速率限制通常需要基于用户身份或 IP 地址,而这些信息在认证后更明确。

配置限制类

可以通过 throttle_classes 属性指定限制。例如:

from rest_framework.views import APIView
from rest_framework.throttling import UserRateThrottleclass MyAPIView(APIView):throttle_classes = [UserRateThrottle]def get(self, request):return Response({"message": "Request allowed"})
内置限制类

DRF 提供了一些常用的限制类:

  • AnonRateThrottle: 限制匿名用户的请求速率,基于 IP 地址。
  • UserRateThrottle: 限制认证用户的请求速率,基于用户 ID。
  • ScopedRateThrottle: 限制特定视图的请求速率,可以通过 throttle_scope 属性配置。

限制速率在 settings.py 中通过 REST_FRAMEWORK 配置。例如:

REST_FRAMEWORK = {'DEFAULT_THROTTLE_CLASSES': ['rest_framework.throttling.AnonRateThrottle','rest_framework.throttling.UserRateThrottle',],'DEFAULT_THROTTLE_RATES': {'anon': '100/day',  # 匿名用户每天 100 次请求'user': '1000/day',  # 认证用户每天 1000 次请求}
}
自定义限制

可以创建自定义限制类。例如,限制特定用户组的请求速率:

from rest_framework.throttling import SimpleRateThrottleclass PremiumUserThrottle(SimpleRateThrottle):scope = 'premium'def get_cache_key(self, request, view):if request.user.is_authenticated and request.user.is_premium:return f"throttle_{request.user.id}"return None

settings.py 中配置:

REST_FRAMEWORK = {'DEFAULT_THROTTLE_RATES': {'premium': '5000/day',}
}
注意事项
  • 缓存依赖:速率限制通常需要配置缓存后端(如 Redis),否则可能无法正常工作。
  • 匿名用户限制:基于 IP 的限制可能不准确,因为多个用户可能共享同一 IP(如代理服务器)。
  • 动态限制:可以通过 throttle_scope 和自定义限制类实现基于视图或用户的动态限制。
  • 错误响应:429 响应会包含 Retry-After 头,指示客户端需要等待的时间。
常见使用场景
  • 防止滥用:限制匿名用户对公开 API 的频繁访问。
  • 分级服务:为不同用户组(如免费用户、付费用户)设置不同的请求速率。
  • 保护资源:避免服务器因高频请求过载。

综合分析与优化建议

执行顺序的意义

perform_authenticationcheck_permissionscheck_throttles 的调用顺序是有意设计的:

  1. 先认证:确保 request.userrequest.auth 已设置,因为权限和限制可能依赖这些信息。
  2. 再检查权限:基于认证结果判断用户是否有权访问资源。
  3. 最后限制速率:确保只有合法请求才会计入速率限制,避免浪费配额。
性能优化
  • 认证:选择轻量级的认证方式(如 JWT 比 Session 更适合无状态 API),并缓存频繁查询的用户数据。
  • 权限:将复杂的权限检查逻辑移到对象级(has_object_permission),减少视图级检查的开销。
  • 限制:使用高效的缓存后端(如 Redis),并合理设置限制周期(如小时、天)以平衡性能和安全性。
扩展性
  • 模块化设计:DRF 的认证、权限和限制机制高度模块化,允许通过自定义类实现复杂逻辑。
  • 全局配置:在 settings.py 中通过 REST_FRAMEWORK 设置默认的认证、权限和限制类,减少重复代码。
  • 动态调整:通过 get_authenticatorsget_permissionsget_throttles 方法动态返回认证、权限或限制类,实现基于视图或请求的灵活配置。
常见问题与解决方案
  • 401 vs. 403
    • 401 Unauthorized:认证失败(如无效的令牌)。
    • 403 Forbidden:认证成功但权限不足。
    • 解决方案:确保认证和权限类的错误信息清晰,方便调试。
  • 速率限制不生效:检查是否正确配置了缓存后端(如 CACHES 设置)。
  • 匿名用户问题:明确区分匿名和认证用户的处理逻辑,避免意外允许敏感操作。
实际案例

假设你正在开发一个博客 API,需求如下:

  • 匿名用户可以读取文章(GET)。
  • 认证用户可以创建文章(POST),但每天限制 10 次请求。
  • 管理员可以编辑所有文章(PUT)。

实现代码如下:

from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.throttling import UserRateThrottle
from rest_framework.response import Responseclass ArticleAPIView(APIView):authentication_classes = [TokenAuthentication]permission_classes = [IsAuthenticated]throttle_classes = [UserRateThrottle]def get_permissions(self):if self.request.method == 'GET':return [AllowAny()]elif self.request.method == 'PUT':return [IsAdminUser()]return super().get_permissions()def get(self, request):return Response({"message": "List of articles"})def post(self, request):return Response({"message": "Article created"})def put(self, request):return Response({"message": "Article updated"})

settings.py 中:

REST_FRAMEWORK = {'DEFAULT_THROTTLE_RATES': {'user': '10/day',}
}

总结

  • perform_authentication:负责用户认证,将用户信息绑定到请求对象,依赖 authentication_classes
  • check_permissions:检查用户权限,决定是否允许访问,依赖 permission_classes
  • check_throttles:限制请求速率,防止滥用,依赖 throttle_classes
  • 设计哲学:DRF 通过模块化的认证、权限和限制机制,提供灵活且可扩展的 API 开发框架。
  • 优化与实践:合理配置认证、权限和限制类,结合缓存和动态调整,满足复杂业务需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/89956.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/89956.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/89956.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神经网络——卷积层

目录 卷积层介绍 Conv2d 卷积动画演示 卷积代码演示 综合代码案例 卷积层介绍 卷积层是卷积神经网络(CNN)的核心组件,它通过卷积运算提取输入数据的特征。 基本原理 卷积层通过卷积核(过滤器)在输入数据&…

神经网络——线性层

在机器学习中,线性层(Linear Layer) 是一种基础的神经网络组件,也称为全连接层(Fully Connected Layer) 或密集层(Dense Layer)。 其严格的数学定义为:对输入数据执行线…

大模型高效适配:软提示调优 Prompt Tuning

The Power of Scale for Parameter-Efficient Prompt Tuning ruatishi 软提示向量 具体是什么 《The Power of Scale for Parameter-Efficient Prompt Tuning》中增加的部分是“软提示(soft prompts)”,这是一种针对特定下游任务,添加到输入文本中的可调参数序列。它与传统…

https正向代理 GoProxy

背景: 在安全隔离的内网环境中,部署于内网的应用如需调用公网第三方接口(如支付、短信),可通过正向代理服务实现访问。 GoProxy 下载: https://github.com/snail007/goproxy/releases 使用文档&#xff…

Java IO流体系详解:字节流、字符流与NIO/BIO对比及文件拷贝实践

一、字节流与字符流:如何选择? 1.1 核心区别特性字节流字符流处理单位字节(8位)字符(16位Unicode)适用场景二进制文件(图片/视频)文本文件(TXT/CSV)编码处理需…

QT6 源,七章对话框与多窗体(5) 文件对话框 QFileDialog 篇二:源码带注释

&#xff08;13&#xff09;本源代码定义于头文件 qfiledialog . h &#xff1a; #ifndef QFILEDIALOG_H #define QFILEDIALOG_H#include <QtWidgets/qtwidgetsglobal.h> #include <QtCore/qdir.h> #include <QtCore/qstring.h> #include <QtCore/qurl.h…

关于Ajax的学习笔记

Ajax概念&#xff1a;是一门使用了js语言&#xff0c;可以使用于Javaweb&#xff0c;实现前端代码和后端代码连结的的一种异步同步&#xff08;不需要等待服务器相应&#xff0c;就能够发送第二次请求&#xff09;的一种技术&#xff0c;它主要用于网页内容的局部刷新&#xff…

The Missing Semester of Your CS Education 学习笔记以及一些拓展知识(三)

文章目录The Missing Semester of Your CS Education 学习笔记以及一些拓展知识Vim编辑器笔记部分程序员常用的编辑器Vim的模式Vim的普通模式Vim的插入模式Vim的可视模式Vim的替换模式Vim的命令行模式Vim的高级功能文本对象宏寄存器缓冲区标记代码折叠Vim的常用配置Vim的常用插…

PyTorch常用的简单数学运算

一、基础算术运算1. 逐元素运算a torch.tensor([1, 2, 3]) b torch.tensor([4, 5, 6])# 加减乘除 a b # [5, 7, 9] a - b # [-3, -3, -3] a * b # [4, 10, 18] a / b # [0.25, 0.4, 0.5]# 幂运算、平方根 a ** 2 # [1, 4, 9] torch.sqrt(a) # [1.0, 1.414, 1.732]2. 标…

C++ Lambda 表达式详解:从基础到实战

Lambda 表达式是 C11 引入的重要特性&#xff0c;它允许我们在代码中定义匿名函数&#xff0c;极大地简化了代码编写&#xff0c;尤其是在使用 STL 算法和多线程编程时。本文将详细介绍 Lambda 表达式的语法、特性及实际应用场景。什么是 Lambda 表达式&#xff1f;Lambda 表达…

Spring Boot注解详解

文章目录前言1. 核心启动注解SpringBootApplicationEnableAutoConfigurationSpringBootConfiguration2. 组件注解Component及其衍生注解ComponentServiceRepositoryControllerRestController3. 依赖注入注解AutowiredQualifierPrimary4. Web相关注解请求映射注解RequestMapping…

Web开发:ABP框架12——中间件Middleware的创建和使用

一、简介中间件可以用于鉴权、日志&#xff0c;拦截器可以用于指定方法或url的业务逻辑处理&#xff0c;两者分工不同&#xff0c;实现效果相似&#xff0c;先执行中间件&#xff0c;后执行拦截器&#xff0c;再到WebAPI接口。二、示例一个Token验证中间件三、代码1.Startup.cs…

京东商品评论如何获取?API接口实战指南

一、API接入准备1. 注册开发者账号访问京东开放平台&#xff1a;前往京东开放平台注册账号&#xff0c;完成企业或个人实名认证。创建应用&#xff1a;在控制台创建应用&#xff0c;获取App Key和App Secret&#xff08;用于签名认证&#xff09;。2. 申请API权限搜索接口&…

leetcode-sql-627变更性别

题目&#xff1a; Salary 表&#xff1a; --------------------- | Column Name | Type | --------------------- | id | int | | name | varchar | | sex | ENUM | | salary | int | --------------------- id 是这个表的主键…

【学习路线】C#企业级开发之路:从基础语法到云原生应用

一、C#基础入门&#xff08;1-2个月&#xff09; &#xff08;一&#xff09;开发环境搭建Visual Studio安装配置 Visual Studio Community&#xff1a;免费版本&#xff0c;功能完整Visual Studio Code&#xff1a;轻量级&#xff0c;跨平台支持JetBrains Rider&#xff1a;专…

Planning Agent:基于大模型的动态规划与ReAct机制,实现复杂问题自适应执行求解

引言 在当今数据驱动的商业环境中&#xff0c;企业面临着日益复杂的决策问题。传统的数据分析工具往往难以应对多步骤、多依赖的复杂问题求解。例如&#xff0c;当企业需要分析"北美市场 Q1-Q2 主要产品的销售增长趋势并识别关键驱动因素"时&#xff0c;传统工具可能…

人该怎样活着呢?55

人该怎样活着呢&#xff1f; A思考现实问题并记录自己的灵感 。【生活的指南针】 &#xff08;20250212&#xff09; a1如何思考&#xff1f; 当有人问他用什么方法得到那么多发现时&#xff0c;牛顿说&#xff1a;“我只不过对于一件事情&#xff0c;总是花很长时间很热…

rtthread - V5.1.0版本 HOOK 钩子函数总结

rtthread - V5.1.0版本 钩子函数 相对于V4.0.3版本做了很大的修改和优化&#xff1a;旧版本 V4.0.3&#xff1a;rt_thread_inited_sethook(thread_inited_hook);rt_thread_deleted_sethook(thread_deleted_hook);rt_scheduler_sethook(scheduler_hook);新版本 V5.1.0&#xff1…

Python特性:装饰器解决数据库长时间断连问题

前言 在基于 Python 的 Web 应用开发里&#xff0c;数据库连接是极为关键的一环。不过&#xff0c;像网络波动、数据库服务器维护这类因素&#xff0c;都可能造成数据库长时间断连&#xff0c;进而影响应用的正常运作。本文将详细介绍怎样运用 retry_on_failure 装饰器来解决数…

疗愈之手的智慧觉醒:Deepoc具身智能如何重塑按摩机器人的触觉神经

疗愈之手的智慧觉醒&#xff1a;Deepoc具身智能如何重塑按摩机器人的触觉神经康复中心的理疗室内&#xff0c;一位运动员正俯卧在治疗床上。机械臂的硅胶触头沿腰背肌群缓缓移动&#xff0c;当传感器捕捉到竖脊肌的异常僵直时&#xff0c;触头自动切换高频震颤模式&#xff1b;…