PHP项目如何配置站点超时跳转?

wen PHP项目 72

本文目录导读:

PHP项目如何配置站点超时跳转?

  1. 方案一:基于 Session 过期时间的跳转(用户无操作超时)
  2. 方案二:PHP 脚本执行超时跳转(防止长时间运行)
  3. 方案三:JavaScript 前端主动监测与跳转(配合后端)
  4. 方案四:.htaccess 或 Nginx 配置层超时(HTTP 请求超时)
  5. 方案五:配置框架级别的超时(以 Laravel 为例)
  6. 推荐组合策略

在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 主动监测 结合:

  1. 后端session_check.php 或框架中间件):

    • 记录 $_SESSION['last_activity']
    • 每次请求检查是否超过设定时间(如30分钟)
    • 超时则销毁 Session 并跳转到登录页
  2. 前端(全局 JavaScript):

    • 使用 setTimeout 设定一个计数
    • 监听鼠标移动、键盘等事件重置计时器
    • 达到阈值时先尝试 Ajax 请求检查 Session 有效性,再跳转
  3. 关键点

    • 超时时间建议同时配置在 session.gc_maxlifetimesession.cookie_lifetime
    • 跳转时附带 ?timeout=1 参数以便显示友好的提示信息
    • 如果是 REST API 项目,超时跳转应返回 401 状态码,由前端处理跳转

这样既保证了安全性(后端强制超时),又提升了用户体验(前端主动无感监测)。

抱歉,评论功能暂时关闭!