Django生产环境用户登录状态反复切换问题求助
问题排查与解决方案
你的问题核心是生产环境下(DigitalOcean Ubuntu + Gunicorn + Nginx)登录后刷新页面,request.user.is_authenticated状态反复切换,以下是针对性的排查和修复步骤:
1. 优先修复:is_authenticated调用错误
Django 1.10+版本中,request.user.is_authenticated是布尔属性而非方法,旧版本的is_authenticated()调用方式在新版本中会引发逻辑错误(甚至报错)。这很可能是本地与生产环境Django版本不一致导致的状态波动。
修改你的中间件代码:
# middleware.py def middleware(request): # 移除 is_authenticated 后的括号 if (request.path.startswith('/dashboard') or 'account' in request.path) and not request.user.is_authenticated: context = { "title": "Not logged in", "message": "- You are not logged in." } return render(request, '403.html', context) # 剩余代码不变
2. 确认中间件加载顺序
Django的AuthenticationMiddleware负责初始化request.user对象,如果你的自定义中间件在它之前加载,会导致request.user未被正确初始化,引发状态判断异常。
检查settings.py中的MIDDLEWARE配置,确保顺序如下:
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', 'myapp.middleware.IsAuthMiddleware', # 你的自定义中间件 ]
3. 修复Nginx代理配置(关键)
生产环境中Nginx如果未正确传递Cookie或开启了页面缓存,会导致Session状态无法同步。
正确的代理配置示例
server { listen 80; server_name your-domain.com; # 重定向HTTP到HTTPS(如果启用了HTTPS) return 301 https://$host$request_uri; } server { listen 443 ssl; server_name your-domain.com; # SSL证书配置省略... location / { proxy_pass http://127.0.0.1:8000; # 必须传递的请求头,确保Session Cookie正常传递 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Cookie $http_cookie; # 禁用认证页面的缓存,避免状态固化 proxy_cache_bypass $http_cookie; proxy_no_cache $http_cookie; } # 静态文件配置省略... }
4. 调整Django Session配置
针对生产环境HTTPS场景,确保Session Cookie的安全性和有效性:
# settings.py SESSION_COOKIE_SECURE = True # HTTPS下强制Cookie仅通过HTTPS传输 SESSION_COOKIE_HTTPONLY = True # 防止前端JS读取Cookie,提升安全性 SESSION_COOKIE_DOMAIN = "your-domain.com" # 匹配你的域名,避免跨域Cookie问题 SESSION_ENGINE = "django.contrib.sessions.backends.db" # 或使用Redis等共享存储
5. Gunicorn配置检查
如果使用多Worker模式,确保Session存储是跨进程共享的(如数据库、Redis),避免使用默认的文件存储(每个Worker的Session文件独立,会导致状态不一致)。
启动Gunicorn时建议使用sync模式(避免异步带来的Session同步问题):
gunicorn --workers 3 --worker-class sync your-project.wsgi:application
内容的提问来源于stack exchange,提问作者RaphSinai
相关产品推荐
相关产品推荐

