PHP 会话在 30 分钟后过期:4 种有效方法

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:“为什么我的会话不会过期?”

\n\n

想象一下:您正在编写一个在线商店、管理后台或个人账户。用户登录、操作、然后去喝咖啡——但一小时后,他的会话仍然有效。购物车数据还在,访问权限仍然开放。这不仅不方便,而且很危险。特别是如果网站处理支付数据。

\n\n

“How do I expire a PHP session after 30 minutes?” 这个问题是 Stack Overflow 上最热门的问题之一(有数万次浏览)。这并不奇怪:初级开发人员通常认为只需设置 session.gc_maxlifetime 就能搞定。然后他们惊讶地发现会话持续了几个小时。

\n\n

在本文中,我们将介绍 4 种实际方法,让 PHP 会话在 30 分钟后精确过期。您将了解为什么标准设置可能失效,以及如何根据您的需求选择合适的方法。开始吧!

\n\n

一点理论:PHP 如何管理会话时间

\n\n

在编写代码之前,了解影响会话“过期”的两个机制很重要:

\n\n
    \n
  • 会话 cookie 的生命周期——浏览器存储会话标识符(PHPSESSID)的时间。由 session.cookie_lifetime 参数控制。
  • \n
  • 服务器上数据的生命周期——会话文件在 /tmp 文件夹中保留的时间。由 session.gc_maxlifetime 控制。
  • \n
\n\n

问题在于,垃圾回收器(GC)是概率性运行的。默认情况下,它在 1% 的请求中触发。这意味着即使 gc_maxlifetime = 1800(30 分钟),会话也可能再挂起一个小时,直到 GC 处理到它。

\n\n

因此,仅依赖服务器设置是个坏主意。您需要“手动”检查时间。

\n\n

方法 1. 经典方法:在会话中检查时间(推荐)

\n\n

这是最可靠、最透明的方法。您自己在会话中存储最后活动的时间戳,并在每次请求时检查是否已过 30 分钟。

\n\n
<?php\nsession_start();\n\n// 设置会话生命周期——30 分钟(1800 秒)\n$timeout_duration = 1800;\n\n// 如果会话中有时间戳且已过期\nif (isset($_SESSION['LAST_ACTIVITY']) && \n    (time() - $_SESSION['LAST_ACTIVITY']) > $timeout_duration) {\n    // 销毁会话\n    session_unset();\n    session_destroy();\n    // 重定向到登录页面\n    header("Location: login.php?timeout=1");\n    exit;\n}\n\n// 更新时间戳(如果用户活跃)\n$_SESSION['LAST_ACTIVITY'] = time();\n?>
\n\n

优点:

\n
    \n
  • 绝对控制:会话将在不活动 30 分钟后精确过期。
  • \n
  • 不依赖 PHP 设置和垃圾回收器。
  • \n
  • 易于为网站的不同部分更改时间(例如,管理后台 15 分钟,用户 60 分钟)。
  • \n
\n\n

缺点:

\n
    \n
  • 需要在每个页面上添加检查(或将其提取到通用初始化文件中)。
  • \n
  • 如果用户保持页面打开但不点击——会话将过期。对于某些场景(长表单),这是一个缺点。
  • \n
\n\n

方法 2. 组合方法:gc_maxlifetime + cookie_lifetime

\n\n

如果您不想编写手动检查,可以尝试“开箱即用”地配置 PHP。但请记住其中的细微差别。

\n\n
// 在脚本开头,session_start() 之前\n$lifetime = 1800; // 30 分钟\n\n// 设置会话 cookie 的生命周期\nsession_set_cookie_params($lifetime);\n\n// 设置服务器上数据的最大生命周期\nini_set('session.gc_maxlifetime', $lifetime);\n\n// 现在启动会话\nsession_start();
\n\n

另外——为了让 GC 更频繁地运行,可以减少触发概率:

\n\n
ini_set('session.gc_probability', 1);\nini_set('session.gc_divisor', 1); // GC 将在每次请求时运行                

博客

书籍推荐