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

Django自定义Token认证中间件及视图排除方法咨询

我来帮你搞定这个问题!在Django里实现部分视图需要Token身份验证、部分视图允许匿名访问的需求,有几种实用方案,我逐个给你拆解清楚:

方案一:自定义Token认证中间件(适配普通Django视图)

如果你用的是普通Django视图(非DRF),自定义中间件是最直接的方式,核心思路是在中间件里判断当前请求的视图是否在“豁免列表”里,在的话跳过认证,否则执行Token验证。

步骤1:编写中间件代码

在你的app目录下新建middleware.py,写入以下代码:

from django.http import JsonResponse
from django.utils.deprecation import MiddlewareMixin
from rest_framework.authtoken.models import Token

class TokenAuthMiddleware(MiddlewareMixin):
    # 定义不需要认证的视图:支持视图完整路径或URL名称
    EXEMPT_VIEWS = [
        # 方式1:视图函数的完整模块路径
        'myapp.views.public_home',
        'myapp.views.visitor_login',
        # 方式2:URL配置里的name值(需要在urls.py给对应URL命名)
        'public_api',
        'guest_register'
    ]

    def process_view(self, request, view_func, view_args, view_kwargs):
        # 检查当前视图是否在豁免列表中
        # 获取视图的完整模块名称
        view_full_name = f"{view_func.__module__}.{view_func.__name__}"
        # 获取URL配置的name值
        url_name = request.resolver_match.url_name if request.resolver_match else None
        
        if view_full_name in self.EXEMPT_VIEWS or url_name in self.EXEMPT_VIEWS:
            return None  # 跳过认证,继续处理请求

        # 执行Token认证逻辑
        auth_header = request.META.get('HTTP_AUTHORIZATION')
        if not auth_header or not auth_header.startswith('Token '):
            return JsonResponse({'error': '请提供Token认证信息'}, status=401)
        
        token_key = auth_header.split(' ')[1]
        try:
            token = Token.objects.get(key=token_key)
            request.user = token.user  # 将认证通过的用户绑定到request对象
        except Token.DoesNotExist:
            return JsonResponse({'error': '无效的Token'}, status=401)
        
        return None

步骤2:配置中间件

在项目的settings.py中,把这个中间件加入到MIDDLEWARE列表里(注意顺序,建议放在django.contrib.auth.middleware.AuthenticationMiddleware之后):

MIDDLEWARE = [
    # ... 其他默认中间件
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'myapp.middleware.TokenAuthMiddleware',  # 你的自定义中间件
    # ... 其他中间件
]

小提示

  • 可以把豁免列表移到settings.py里,比如定义EXEMPT_TOKEN_VIEWS = [...],然后在中间件里from django.conf import settings再引用,这样更便于统一管理。
  • 如果你的视图返回的是HTML页面而非JSON,可以把响应改成redirect或者返回401页面,按需调整。
方案二:用DRF自带的认证+权限系统(适配DRF视图)

如果你的项目用了Django REST Framework(DRF),那完全不用自己写中间件,DRF已经封装好了成熟的认证和权限控制逻辑:

步骤1:全局配置默认认证

在settings.py里设置全局默认的认证和权限类,让所有视图默认需要Token认证:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ]
}

步骤2:给指定视图豁免认证

在不需要认证的DRF视图里,覆盖permission_classes属性为AllowAny即可:

from rest_framework.views import APIView
from rest_framework.permissions import AllowAny
from rest_framework.response import Response

class PublicAPIView(APIView):
    permission_classes = [AllowAny]  # 允许匿名访问

    def get(self, request):
        return Response({'message': '这是一个公开接口,无需认证'})

这种方式最省心,DRF会自动处理Token解析、异常响应等细节,非常推荐使用。

方案三:用装饰器给单个视图加认证(适合少量视图需要认证的场景)

如果你的大部分视图是公开的,只有少数需要Token认证,那用装饰器更灵活:

步骤1:编写认证装饰器

在app目录下新建decorators.py,写入:

from django.http import JsonResponse
from rest_framework.authtoken.models import Token
from functools import wraps

def token_required(view_func):
    @wraps(view_func)
    def wrapped_view(request, *args, **kwargs):
        auth_header = request.META.get('HTTP_AUTHORIZATION')
        if not auth_header or not auth_header.startswith('Token '):
            return JsonResponse({'error': '需要Token认证'}, status=401)
        
        token_key = auth_header.split(' ')[1]
        try:
            token = Token.objects.get(key=token_key)
            request.user = token.user
        except Token.DoesNotExist:
            return JsonResponse({'error': '无效Token'}, status=401)
        
        return view_func(request, *args, **kwargs)
    return wrapped_view

步骤2:在视图中使用装饰器

给需要认证的视图加上装饰器,公开视图直接写:

from django.shortcuts import render
from .decorators import token_required

@token_required
def user_dashboard(request):
    return render(request, 'dashboard.html', {'user': request.user})

def public_home(request):
    return render(request, 'home.html')
总结选择建议
  • 大部分视图需认证,少数公开:选自定义中间件(普通视图)或DRF全局配置+AllowAny(DRF视图)
  • 大部分视图公开,少数需认证:选装饰器方案
  • 用DRF开发API:优先用DRF自带的认证权限系统,减少重复造轮子

内容的提问来源于stack exchange,提问作者Sumit Badsara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:52:28