本文目录导读:

- 方案一:基于 Session 过期时间的跳转(用户无操作超时)
- 方案二:PHP 脚本执行超时跳转(防止长时间运行)
- 方案三:JavaScript 前端主动监测与跳转(配合后端)
- 方案四:.htaccess 或 Nginx 配置层超时(HTTP 请求超时)
- 方案五:配置框架级别的超时(以 Laravel 为例)
- 推荐组合策略
在PHP项目中配置站点超时跳转,通常有几种常见的实现方式,具体取决于你对“超时”的定义(是用户无操作超时,还是PHP脚本执行超时,还是会话过期)。
以下是几种常见的配置和实现方案:
基于 Session 过期时间的跳转(用户无操作超时)
这是最常见的需求:用户登录后一段时间无操作,自动跳转到登录页。
步骤 1:设置 Session 超时时间
在 php.ini 或项目入口文件(如 index.php)中设置:
// 设置 Session 生命周期(秒)
session_set_cookie_params(3600); // 1小时
// 或设置 gc 最大存活时间
ini_set('session.gc_maxlifetime', 3600);
// 设置客户端 cookie 过期时间
ini_set('session.cookie_lifetime', 3600);
session_start();
步骤 2:检查最后活动时间(推荐方式)
在用户每次请求时记录 $_SESSION['last_activity'],对比当前时间:
session_start();
$timeout = 1800; // 30分钟无操作视为超时
if (isset($_SESSION['last_activity']) && (time() - $_SESSION['last_activity'] > $timeout)) {
// 超时处理:清除会话并跳转
session_unset();
session_destroy();
header('Location: login.php?timeout=1');
exit();
}
// 更新最后活动时间
$_SESSION['last_activity'] = time();
步骤 3:在登录页面显示提示
// login.php
if (isset($_GET['timeout'])) {
echo '<div class="alert">会话已超时,请重新登录。</div>';
}
PHP 脚本执行超时跳转(防止长时间运行)
如果某个 PHP 脚本执行时间过长需要终止并跳转。
方法 1:使用 set_time_limit()
ini_set('max_execution_time', 300); // 设置最大执行时间 300 秒
try {
// 执行可能超时的任务
$result = someLongProcess();
} catch (Exception $e) {
// 超时异常无法直接捕获(PHP 默认超时是致命错误)
// 需要通过 register_shutdown_function 处理
}
// 更可靠的方式:自定义超时时间检查
$startTime = time();
$maxTime = 300; // 5分钟
while (time() - $startTime < $maxTime) {
// 处理逻辑
if (/* 处理完成 */) {
break;
}
}
// 超时处理
if (time() - $startTime >= $maxTime) {
header('Location: timeout.php');
exit;
}
方法 2:使用 register_shutdown_function 捕获致命错误
register_shutdown_function(function() {
$error = error_get_last();
if ($error && $error['type'] === E_ERROR) {
// 检查是否是超时错误
if (strpos($error['message'], 'Maximum execution time') !== false) {
header('Location: timeout.php');
exit;
}
}
});
JavaScript 前端主动监测与跳转(配合后端)
更适合用户体验,无需刷新页面即可感知超时。
// 在页面中添加
let sessionTimeout;
const timeoutDuration = 1800000; // 30分钟
function resetSessionTimer() {
clearTimeout(sessionTimeout);
sessionTimeout = setTimeout(() => {
// 先请求后端检查会话是否仍然有效
fetch('/check-session.php')
.then(res => res.json())
.then(data => {
if (!data.valid) {
window.location.href = 'login.php?timeout=1';
}
});
}, timeoutDuration);
}
// 监听用户活动
document.addEventListener('mousemove', resetSessionTimer);
document.addEventListener('keypress', resetSessionTimer);
document.addEventListener('click', resetSessionTimer);
对应的后端 check-session.php:
session_start();
header('Content-Type: application/json');
if (!isset($_SESSION['user_id']) || !isset($_SESSION['last_activity'])) {
echo json_encode(['valid' => false, 'timeout' => true]);
exit;
}
if (time() - $_SESSION['last_activity'] > 1800) {
session_destroy();
echo json_encode(['valid' => false, 'timeout' => true]);
exit;
}
$_SESSION['last_activity'] = time();
echo json_encode(['valid' => true]);
.htaccess 或 Nginx 配置层超时(HTTP 请求超时)
如果超时不是由业务逻辑决定,而是服务器配置决定:
Apache (.htaccess)
# 单个 PHP 请求超时(秒)
<IfModule mod_php.c>
php_value max_execution_time 300
php_value max_input_time 300
</IfModule>
# 整个连接超时(用 mod_reqtimeout)
RequestReadTimeout header=20-40,MinRate=500 body=30,MinRate=500
Nginx (nginx.conf)
# 在 server 或 location 块中 fastcgi_read_timeout 300; proxy_read_timeout 300; # 如果有自定义超时页面 error_page 504 /timeout.html;
配置框架级别的超时(以 Laravel 为例)
Laravel Session 过期设置
config/session.php:
'lifetime' => 120, // 分钟 'expire_on_close' => true, // 关闭浏览器即过期
Laravel 自定义超时中间件
// app/Http/Middleware/CheckSessionTimeout.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class CheckSessionTimeout
{
public function handle($request, Closure $next)
{
if (Auth::check()) {
$lastActivity = session('last_activity');
$timeout = config('session.lifetime') * 60;
if ($lastActivity && (time() - $lastActivity > $timeout)) {
Auth::logout();
session()->flush();
return redirect('login')->with('message', '会话已超时');
}
session(['last_activity' => time()]);
}
return $next($request);
}
}
推荐组合策略
最好的方案是 后端 Session 检查 + 前端 JS 主动监测 结合:
-
后端(
session_check.php或框架中间件):- 记录
$_SESSION['last_activity'] - 每次请求检查是否超过设定时间(如30分钟)
- 超时则销毁 Session 并跳转到登录页
- 记录
-
前端(全局 JavaScript):
- 使用
setTimeout设定一个计数 - 监听鼠标移动、键盘等事件重置计时器
- 达到阈值时先尝试 Ajax 请求检查 Session 有效性,再跳转
- 使用
-
关键点:
- 超时时间建议同时配置在
session.gc_maxlifetime和session.cookie_lifetime - 跳转时附带
?timeout=1参数以便显示友好的提示信息 - 如果是 REST API 项目,超时跳转应返回 401 状态码,由前端处理跳转
- 超时时间建议同时配置在
这样既保证了安全性(后端强制超时),又提升了用户体验(前端主动无感监测)。