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

Ubuntu22服务器部署Django登录后持续重定向至登录页问题求解

问题

在Ubuntu 22服务器上以Nginx作为应用服务器部署Django应用,但登录系统后,每次请求都会被重定向回登录页。

认证实现代码

if form.is_valid():
    username = form.cleaned_data.get("username")
    password = form.cleaned_data.get("password")
    logger.debug(f"Attempting to authenticate user {username}.")
    user = authenticate(username=username, password=password)

    if user is not None:
        logger.debug(f"Authenticated user {username}.")
        login(request, user)
        if user.role == 'STAFF':
            return redirect("sales:sales_list")
        elif user.role in ["MANAGER", "SUPERVISOR",]:
            return redirect("authentication:manager_dashboard")
        elif user.role in ["ADMIN", "GENERAL", "CEO"]:
            return redirect('master:index')

SalesListView实现

class SalesListView(ListView):
    """
    View for displaying sales transactions.

    Requires user to be logged in and have specific roles (STAFF, MANAGER, ADMIN, SUPERVISOR, CEO).
    Displays sales data based on user role and branch.
    """

    template_name = "manager/purchase/sales.html"
    model = Sale
    context_object_name = "sales"

    def dispatch(self, request, *args, **kwargs):
        """
        Custom dispatch method to handle role-based template selection.

        Sets different template names based on the user's role.
        """
        user = request.user

        if not user.is_authenticated:
            # If not authenticated, redirect to login page
            messages.error(request, 'You need to log in first!', extra_tags="danger")
            return redirect('authentication:login')

        self.branch = user.branch.id
        self.user_role = user.role

        print(f"User branch {self.branch} : user role {self.user_role}")

        if self.user_role == 'STAFF':
            self.template_name = 'team_member/sales/sales.html'  # Set template for staff role
        # TODO: Add logic for other roles and master view

        return super().dispatch(request, *args, **kwargs)

缓存及Session配置

SESSION_COOKIE_AGE = 7200 
SESSION_EXPIRE_AT_BROWSER_CLOSE = False 
SECURE_HSTS_SECONDS = 31536000

CACHES = { 
    'default': { 
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 
        'LOCATION': 'unique-snowflake', 
        'TIMEOUT': 300, 
        'OPTIONS': { 
            'MAX_ENTRIES': 1000, 
            'CULL_FREQUENCY': 3, 
        } 
    } 
}

# Session Engine
SESSION_ENGINE = "django.contrib.sessions.backends.cache" 
SESSION_CACHE_ALIAS = "default"
解决方案

1. 替换LocMemCache为集中式缓存

LocMemCache是进程内缓存,如果你用Gunicorn/uWSGI等多进程方式运行Django,每个进程会维护独立的缓存实例,会话数据无法在进程间共享,导致跨请求时用户身份丢失。

解决办法:

  • 改用Redis或Memcached这类集中式缓存。以Redis为例:
    1. 安装依赖:pip install django-redis redis
    2. 修改settings.py中的缓存配置:
      CACHES = {
          'default': {
              'BACKEND': 'django_redis.cache.RedisCache',
              'LOCATION': 'redis://127.0.0.1:6379/1',
              'OPTIONS': {
                  'CLIENT_CLASS': 'django_redis.client.DefaultClient',
              }
          }
      }
      
  • 临时测试可以改用数据库存储会话:
    SESSION_ENGINE = "django.contrib.sessions.backends.db"
    

2. 修正Nginx反向代理配置

Nginx需要正确传递请求头,确保Django能识别用户的真实请求并正确处理会话Cookie。在Nginx的server块中添加以下配置:

location / {
    proxy_pass http://127.0.0.1:8000;  # 替换为你的Django服务地址
    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;
}

同时在Django的settings.py中添加:

USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')  # 如果用HTTPS才需要

3. 检查会话Cookie的安全配置

  • 如果你的站点使用HTTPS,必须设置:
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True
    
    否则浏览器可能会拒绝保存会话Cookie。
  • 确认SESSION_COOKIE_DOMAIN设置正确,比如你的服务器域名(如example.com),避免Cookie无法跨请求传递。

4. 排查会话一致性

在SalesListView的dispatch方法中添加日志,打印每次请求的session_key,确认是否一致:

def dispatch(self, request, *args, **kwargs):
    print(f"Session key: {request.session.session_key}")
    # 原有代码...

如果每次请求的session_key都不同,说明会话没有被正确保存,重点检查缓存和Cookie配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 04:25:12