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

Django URL重定向后request.user重置为AnonymousUser问题排查

异常产生原因
  • 中间件注册顺序错误:Django中间件按配置列表从上到下执行process_request逻辑,django.contrib.auth.middleware.AuthenticationMiddleware负责从session中解析用户身份、给request对象绑定user属性。如果自定义的AuthRequiredMiddleware配置在AuthenticationMiddleware之前,执行认证校验时AuthenticationMiddleware还未完成用户解析,拿到的request.user是默认的匿名用户。该问题在静态路由下未暴露,多是因为静态路由命中了框架或服务器的缓存逻辑,未走到自定义中间件的校验分支,配置动态路由后缓存失效触发异常。
  • 路径匹配逻辑缺陷:现有代码用精确字符串相等判断路径是否在豁免列表,完全无法适配带参数的动态路径,也无法正确匹配静态资源、媒体资源等通配路径,容易出现非预期的重定向。比如动态页面中用相对路径引用的资源会被误拦截,反复重定向到登录页的过程中会触发session重置,最终导致已登录用户被识别为匿名用户。
  • 全局缓存逻辑有并发安全问题:代码中用固定key_cached_user在进程全局缓存中存储用户对象,多用户并发请求时会出现缓存值互相覆盖的问题,一旦缓存中存入匿名用户或缓存失效,后续请求读取该缓存时就会拿到错误的用户身份。
修复方案
  1. 调整settings.py中MIDDLEWARE列表的顺序,确保自定义认证中间件在SessionMiddleware、AuthenticationMiddleware之后,参考顺序如下:
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    # 自定义认证中间件放在上述系统中间件之后
    'yourapp.middleware.AuthRequiredMiddleware',
]
  1. 替换精确字符串匹配的路径判断逻辑,改用正则匹配支持动态路径、通配路径,同时把静态资源、媒体资源路径加入豁免列表,修复后的中间件代码参考:
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect
from django.conf import settings
import re

EXEMPT_URLS = []
# 加入登录页豁免规则
if settings.LOGIN_URL:
    EXEMPT_URLS.append(re.compile(r'^%s$' % settings.LOGIN_URL.lstrip('/')))
# 加入配置的自定义豁免路径规则
if hasattr(settings, 'LOGIN_EXEMPT_URLS'):
    for url in settings.LOGIN_EXEMPT_URLS:
        EXEMPT_URLS.append(re.compile(r'^%s$' % url.lstrip('/')))
# 加入静态资源、媒体资源豁免规则
if hasattr(settings, 'STATIC_URL') and settings.STATIC_URL:
    EXEMPT_URLS.append(re.compile(r'^%s.*$' % settings.STATIC_URL.lstrip('/')))
if hasattr(settings, 'MEDIA_URL') and settings.MEDIA_URL:
    EXEMPT_URLS.append(re.compile(r'^%s.*$' % settings.MEDIA_URL.lstrip('/')))

class AuthRequiredMiddleware(MiddlewareMixin):
    def process_request(self, request):
        path = request.path_info.lstrip('/')
        # 命中豁免路径直接放行
        if any(url.match(path) for url in EXEMPT_URLS):
            return
        # 未登录用户重定向到登录页
        if not request.user.is_authenticated:
            return redirect('login')
  1. 删除原代码中全局缓存存储用户的逻辑:request.user已经由Django自带的AuthenticationMiddleware完成解析和绑定,不需要额外存储在全局缓存中,固定key的全局缓存本身存在多用户串号的安全隐患,必须移除。

开发注意:模板中引用静态资源、接口地址时尽量用绝对路径,配合Django自带的{% static %}、{% url %}标签生成地址,避免相对路径被动态路由误解析,触发不必要的拦截。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:18:24