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
相关产品推荐
相关产品推荐

