Django应用sessionid过期异常求助:设置有效期后仍3分钟自动登出
嘿,我来帮你拆解这个头疼的session过期问题——明明设置了SESSION_COOKIE_AGE = 36000(10小时),但实际Cookie显示1969年过期,还3分钟就自动登出,这肯定是某个配置或者代码逻辑覆盖了你的全局设置,咱们一步步排查:
最可能的元凶:SESSION_EXPIRE_AT_BROWSER_CLOSE 设置
首先去你的settings.py里找这个参数:
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
如果它被设为True,那不管你设置多大的SESSION_COOKIE_AGE,都会被覆盖:
- 浏览器端的sessionid Cookie会变成「会话级Cookie」,也就是没有明确过期时间,浏览器会用
1969-12-31T23:59:59.000Z(epoch时间戳0)来标识这种Cookie; - 服务器端的session过期时间虽然还是
SESSION_COOKIE_AGE,但如果你的session后端(比如缓存)有更短的过期策略,或者用户3分钟内没有触发session更新,就会提前失效。
解决办法:把它改成False(默认就是False,可能你不小心开启了),然后重启服务测试。
第二嫌疑:Session 过期时间被代码手动覆盖
检查你整个项目里有没有调用set_expiry()方法的地方,比如在视图、中间件里:
request.session.set_expiry(180) # 手动设置为3分钟过期 request.session.set_expiry(0) # 等同于浏览器关闭即过期
这个方法会针对当前会话单独设置过期时间,直接覆盖全局的SESSION_COOKIE_AGE,如果有这种代码存在,就会出现局部会话提前登出的情况。
解决办法:删掉这些手动设置的代码,或者调整成你需要的10小时(36000秒)。
第三可能:Session 后端的配置问题
如果你用的不是默认的数据库session后端(django.contrib.sessions.backends.db),比如用了Redis、Memcached等缓存后端,要检查:
- 缓存后端有没有单独设置过期时间?比如Redis的配置里有没有给session键设置更短的TTL;
- 如果是数据库后端,去
django_session表里看一下新创建的session的expire_date字段,是不是当前时间加上36000秒,如果不是,说明全局配置没生效。
另外,检查SESSION_SAVE_EVERY_REQUEST参数:
SESSION_SAVE_EVERY_REQUEST = False # 默认值
如果是False,session的过期时间只有在你修改session数据时才会更新。比如用户只是浏览页面(没提交表单、没修改用户信息),那服务器端的session过期时间不会刷新,要是刚好碰到缓存的短时间过期,就会提前登出。可以把它改成True,让每次请求都刷新session过期时间。
排除Gunicorn和Nginx的影响
你提到的Gunicorn worker超时(600秒)和Nginx keepalive_timeout(20分钟),其实和session过期关系不大:
- Gunicorn的worker超时是指worker处理一个请求的最长时间,超时会重启worker,但如果用的是数据库session,worker重启不会丢失session;
- Nginx的keepalive是连接复用设置,和Cookie、session的生命周期完全无关。
不过可以检查Gunicorn日志,有没有频繁的worker重启记录(比如Worker exited with code 3),如果有,可能是资源不足导致,但这不会直接导致3分钟登出。
最后一步:验证Cookie的实际生效情况
修改配置后,打开Chrome的开发者工具(F12)→ Application → Cookies → 你的域名,查看sessionid的Expires/Max-Age:
- 如果显示的是当前时间+10小时,说明配置生效了;
- 如果还是会话级(Session),那说明还有地方在覆盖配置。
内容的提问来源于stack exchange,提问作者Max Miller Silveira

