You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Token无效时让DRF不返回401错误并交由视图处理请求

问题原因

DRF默认的TokenAuthentication存在固定处理逻辑:只要请求携带了Token 前缀的Authorization请求头,就判定该请求需要走Token认证流程,一旦解析到Token值为空、不存在、对应用户失效,会直接抛出AuthenticationFailed异常,全局异常组件会直接返回401响应,完全跳过后续的权限校验、视图逻辑,即便对应视图配置了AllowAny允许匿名访问也不会执行。

解决方案

通过自定义认证类重写异常逻辑,让无效Token场景下不抛出认证异常,而是将请求标记为未认证状态,流转到后续权限、视图层自行处理。

步骤1:自定义宽松模式的Token认证类

在你的业务app下新建authentication.py文件,写入以下代码:

from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.models import Token


class LenientTokenAuthentication(TokenAuthentication):
    def authenticate(self, request):
        # 提取Authorization请求头内容
        auth_header = request.META.get('HTTP_AUTHORIZATION', '')
        # 非Token前缀的认证头直接跳过,和原生逻辑一致
        if not auth_header.startswith(f'{self.keyword} '):
            return None

        # 截取Token实际值
        token_key = auth_header.split(' ', 1)[1].strip()
        # 空Token(比如Token null场景)直接返回认证不通过,不抛错
        if not token_key:
            return None

        # 尝试匹配数据库中的有效Token
        try:
            valid_token = Token.objects.select_related('user').get(key=token_key)
        except Token.DoesNotExist:
            # Token不存在直接返回认证不通过,不触发401
            return None

        # 对应用户被禁用的场景同样不抛错,可按需调整
        if not valid_token.user.is_active:
            return None

        # 只有Token完全有效时,才返回认证通过的用户对象
        return (valid_token.user, valid_token)

步骤2:配置DRF使用自定义认证类

在项目settings.py中替换默认的TokenAuthentication配置:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # 替换原生的rest_framework.authentication.TokenAuthentication
        'your_app.authentication.LenientTokenAuthentication',
        # 保留其他需要的认证类,比如会话认证
        'rest_framework.authentication.SessionAuthentication',
    ],
    # 允许匿名访问的视图需要搭配AllowAny权限使用
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.AllowAny',
    ]
}

补充说明

  • 该认证类和原生逻辑的核心差异仅在于:非法Token场景下不再直接中断请求返回401,而是将request.user设置为匿名用户AnonymousUser流转到后续流程,有效Token的认证逻辑和原生完全一致,不会影响正常登录用户的使用。
  • 如果不需要全局生效,可以不修改全局DEFAULT_AUTHENTICATION_CLASSES配置,仅在需要放行无效Token的视图类/视图函数上单独指定authentication_classes = [LenientTokenAuthentication]即可,其余接口仍保留原生严格校验逻辑。
  • 如果业务需要区分「无Token的普通匿名请求」和「携带无效Token的请求」,可以在返回None之前给request对象打自定义标记,比如request.invalid_token = True,后续视图逻辑中可以读取该标记做定制化处理。

内容的提问来源于stack exchange,提问作者Adilet Usonov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 14:40:01