共享主机是否会导致Flask应用用户异常登出?
该异常和你本地代码逻辑无关,核心是Namecheap Apache共享主机的默认运行机制和Flask/flask_login的默认配置不匹配导致的,本地环境无主机层的强制限制所以运行正常。
Apache全局会话拦截与超时限制
Namecheap共享主机默认开启mod_session模块,全局配置的会话超时阈值为1800秒(30分钟),该模块会优先于你的Flask应用拦截会话Cookie做校验,完全忽略应用层设置的31天Cookie过期时间。
修复方式:在网站根目录的.htaccess文件中添加如下配置,关闭Apache对应用会话的干预:<IfModule mod_session.c> SessionCookieName session_off off </IfModule>临时会话文件被系统定时清理
Flask默认将会话数据存储在系统临时目录/tmp下,Namecheap共享主机配置了定时清理任务,会自动删除/tmp目录下5-30分钟未被系统核心进程访问的文件,会话文件被删除后flask_login自然会判定用户未登录。本地开发环境无这类强制清理规则,所以会话可以长期保留。
修复方式:替换默认的临时文件会话存储为持久化文件存储,将会话存在你私有账号目录下(不要放在web可访问路径、不要放/tmp),参考配置:import os from datetime import timedelta from flask import Flask from flask_session import Session from flask_login import LoginManager app = Flask(__name__) # 提前在账号根目录创建flask_sessions文件夹,设置权限为700,*注意不要将该文件夹放在web根目录下,避免被公网直接访问泄露会话数据* app.config["SESSION_FILE_DIR"] = os.path.expanduser("~/flask_sessions") app.config["SESSION_TYPE"] = "filesystem" app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(days=31) app.config["SESSION_PERMANENT"] = True Session(app) login_manager = LoginManager(app) login_manager.remember_cookie_duration = timedelta(days=31)注意不要使用内存型会话存储,Namecheap共享主机会定时回收闲置的Python应用进程,进程重启后内存中的会话数据会全部丢失。
Cookie作用域不匹配
如果你的站点开启了www/非www重定向、子域名跳转,未显式配置Cookie作用域会导致跨跳转时Cookie不生效,被判定为未登录。
修复方式:补充Cookie相关配置,根据你的站点实际情况调整参数:# 前面加.同时匹配www和非www域名,替换成你自己的域名 app.config["SESSION_COOKIE_DOMAIN"] = ".yourdomain.com" app.config["REMEMBER_COOKIE_DOMAIN"] = ".yourdomain.com" # 站点开启HTTPS则设为True,否则设为False app.config["SESSION_COOKIE_SECURE"] = True app.config["REMEMBER_COOKIE_SECURE"] = True app.config["SESSION_COOKIE_HTTPONLY"] = True app.config["REMEMBER_COOKIE_HTTPONLY"] = True app.config["SESSION_COOKIE_SAMESITE"] = "Lax"
配置修改完成后,先清除浏览器中对应域名的所有历史Cookie,重新登录后打开浏览器开发者工具的应用面板,确认session和remember_token两个Cookie的过期时间为31天后,再做长时登录测试即可。
内容的提问来源于stack exchange,提问作者DMcC

