织梦session失效频繁解决

现象描述

织梦后台管理员或前台会员登录后,短时间内(几分钟到十几分钟)自动掉线,需反复登录。有时操作中途Session丢失导致表单数据丢失,严重影响使用体验。此问题多发于虚拟主机、集群部署或PHP 7+环境。

常见原因分析

  • Session存储目录无写权限:PHP默认把Session存于/tmp,若该目录不可写或被定期清理,Session文件丢失。
  • Session.gc_maxlifetime过短:PHP垃圾回收机制定期清理过期Session,若该值设置过小(如1440秒=24分钟),空闲即被清。
  • 多服务器Session不共享:负载均衡下,请求被分发到不同服务器,各服务器Session独立,导致登录态丢失。
  • Cookie域不匹配:跨子域名访问时Cookie未共享,每次跳转都生成新Session。
  • session.save_path配置错误:路径不存在或磁盘满,Session写入失败。

解决方案一:调整PHP配置

修改php.ini,增大Session存活时间:

session.save_path="/tmp/sessions"  ; 指定独立目录
session.gc_maxlifetime=86400       ; Session存活24小时
session.cookie_lifetime=86400      ; Cookie存活24小时
session.gc_probability=1
session.gc_divisor=1000            ; 垃圾回收概率0.1%

修改后创建Session目录并赋权:

mkdir /tmp/sessions
chmod 777 /tmp/sessions

重启PHP-FPM使配置生效。

虚拟主机无法改php.ini时,可在织梦入口文件/include/common.inc.php开头用ini_set动态设置,但需在session_start()之前调用。

解决方案二:自定义Session存储目录

/include/common.inc.phpsession_start()之前加入:

// 在织梦data目录下建sessions文件夹
$sessionPath=DEDEDATA.'/sessions';
if(!is_dir($sessionPath)){
    @mkdir($sessionPath, 0777, true);
}
session_save_path($sessionPath);
ini_set('session.gc_maxlifetime', 86400);
ini_set('session.cookie_lifetime', 86400);
session_start();

这样Session存于网站目录内,不受服务器/tmp清理影响,迁移时也一并带走。

解决方案三:改用Redis存储Session

集群部署或多服务器场景下,把Session统一存Redis,所有节点共享:

修改php.ini

session.save_handler=redis
session.save_path="tcp://127.0.0.1:6379?auth=yourpassword&database=1"
session.gc_maxlifetime=86400

或在代码中动态设置:

ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://127.0.0.1:6379');
session_start();

需安装PHP的redis扩展(php-redis)。Redis存储的Session天然支持过期,且读取速度快。

方案四:Cookie域配置

跨子域名掉线问题,需让Cookie在所有子域名生效:

session_set_cookie_params(86400, '/', '.example.com');
session_start();

注意.example.com前的点号,表示www.example.comm.example.com等子域名共享。

排查步骤

1. 检查Session是否写入成功

登录后查看Session目录是否有新文件生成:

ls -la /tmp/sessions/

若无新文件,是写权限或路径问题。

2. 查看PHP错误日志

tail -f /var/log/php-fpm/error.log
# 或织梦日志
tail -f /data/logs/*.log

session关键字,看是否有"Failed to write session data"等错误。

3. 打印Session ID

在不同页面输出session_id(),若每次不同说明Cookie未携带,是Cookie域或HTTPS问题。

织梦特有的Session问题

后台验证码频繁失效

后台登录验证码基于Session,若Session失效会提示验证码错误。在/include/vdimgck.php中检查Session写入是否正常。

CSRF token失效

织梦后台表单有token校验,存于Session。Session丢失会报"数据校验不对"。可在/dede/config.php中调整token有效期。

Nginx环境下若开启了fastcgi_cache,可能缓存了带Session的页面,需排除登录态请求。

长期运维建议

建议把Session存储从文件切换到Redis/Memcached,不仅能根治掉线问题,还能为后续多服务器扩展打好基础。同时上线Session监控,统计每日Session丢失率,发现异常及时告警。对敏感操作(如支付、改密码)额外要求二次验证,不单纯依赖Session保活。