使用Django Tenants开发SaaS项目时跨子域重定向丢失用户会话的技术咨询
我之前在基于Django Tenants开发SaaS项目时,也碰到过完全一样的问题——主域登录后跳转到子域,用户直接变成了AnonymousUser,折腾了好一阵才找到核心原因,给你梳理下关键的配置调整和排查点:
1. 核心问题:Cookie的域绑定设置
默认情况下,Django的SESSION_COOKIE_DOMAIN是None,这时候会话Cookie只会绑定到当前请求的具体域名(比如localhost:8000),子域tenant1.localhost:8000根本无法读取这个Cookie。这是导致会话丢失的最主要原因。
你需要在settings.py里明确设置Cookie的域为带前缀点的根域,让所有子域都能共享这个Cookie:
# 允许所有localhost:8000的子域共享会话Cookie SESSION_COOKIE_DOMAIN = '.localhost:8000'
注意前缀的.不能少,它表示"所有以localhost:8000为后缀的域名",这样主域和所有子域都能读取同一个会话Cookie。
2. 确认用户模型与认证配置
因为你的CustomUser放在共享应用(SHARED_APPS)里,必须确保全局的用户模型配置正确,避免子域环境无法识别用户:
# 指向共享应用中的自定义用户模型 AUTH_USER_MODEL = 'account.CustomUser'
同时检查AUTHENTICATION_BACKENDS,确保使用的认证后端能正确从共享schema中读取用户数据(默认的django.contrib.auth.backends.ModelBackend就可以,只要用户模型配置正确)。
3. 检查中间件顺序
Django Tenants的中间件顺序非常关键,必须让TenantMainMiddleware优先于会话和认证中间件执行,这样请求进来时先识别租户,再处理会话:
MIDDLEWARE = [ # 必须放在最前面,先处理租户识别 'django_tenants.middleware.main.TenantMainMiddleware', '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', ]
4. 验证Cookie的实际生效情况
修改配置后,你可以通过浏览器开发者工具验证:
- 主域登录后,查看
Application -> Cookies -> localhost:8000,确认sessionid的Domain字段是.localhost:8000 - 跳转到子域后,同样查看Cookies,应该能看到同一个
sessionid被携带过来
额外注意事项
- 不要在租户专属的配置文件(比如
tenant_settings.py)中重新覆盖SESSION_COOKIE_DOMAIN,否则会破坏全局共享设置 - 本地开发时确保子域能解析到localhost,比如在
hosts文件中添加127.0.0.1 tenant1.localhost - 你当前设置的
SESSION_COOKIE_SAMESITE = 'Lax'是正确的,这个值允许跨域重定向时携带Cookie,换成Strict反而会导致丢失
按照这些步骤调整后,主域的会话应该就能在子域中正常识别了。
内容的提问来源于stack exchange,提问作者Boaz Kalonji

