首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP Session 永不過期實作方案:配置與程式碼雙軌解法

     編輯:PHP 綜合知識

業務痛點

客服系統需求:人員長時間待機不操作,Session 不得過期強制登出。預設 PHP Session 24 分鐘 (1440 秒) 無活動即失效,關閉瀏覽器 Cookie 即銷毀。

方案一:修改 php.ini (擁有主機權限)

; php.ini
session.use_cookies = 1
session.cookie_lifetime = 31536000      ; 1 年 (秒)
session.gc_maxlifetime = 31536000       ; 1 年 (秒)
; 重啟 Apache/PHP-FPM 生效

原理:cookie_lifetime 讓瀏覽器保留 Session ID Cookie 1 年;gc_maxlifetime 讓伺服器端 Session 檔案保留 1 年。GC (垃圾回收) 機率預設 1/1000,長期有效。

方案二:程式碼動態設定 (無 php.ini 權限)

<?php
// 每支腳本最開頭 (或 bootstrap) 執行
session_start();

// 1. 設定伺服器端 Session 存活時間 (秒)
ini_set('session.gc_maxlifetime', 31536000); // 1 年

// 2. 設定 Cookie 存活時間,並覆蓋預設路徑 '/'
$lifetime = 31536000;
session_set_cookie_params($lifetime, '/'); // PHP 5.2+ 可用

// 3. 關鍵:手動重新發送 Cookie,更新 Expire 時間
// session_name() 取得 php.ini session.name (預設 PHPSESSID)
setcookie(session_name(), session_id(), time() + $lifetime, '/');

// 4. 可選:關閉瀏覽器關閉即銷毀 (session.cookie_lifetime=0 行為)
ini_set('session.cookie_lifetime', (string)$lifetime);
?>

方案三:資料庫儲存 Session (分布式/高可用/精確控制)

預設 files handler 受限於單機、GC 不精確。實作 SessionHandlerInterface 存入 MySQL/Redis:

<?php
class DbSessionHandler implements SessionHandlerInterface
{
    private $pdo;
    public function __construct(PDO $pdo) { $this->pdo = $pdo; }

    public function open($savePath, $sessionName) { return true; }
    public function close() { return true; }

    public function read($id) {
        $stmt = $this->pdo->prepare("SELECT data FROM sessions WHERE id = ? AND expiry > ?");
        $stmt->execute([$id, time()]);
        return $stmt->fetchColumn() ?: '';
    }

    public function write($id, $data) {
        $expiry = time() + (int)ini_get('session.gc_maxlifetime');
        $stmt = $this->pdo->prepare("
            INSERT INTO sessions (id, data, expiry) VALUES (?, ?, ?)
            ON DUPLICATE KEY UPDATE data = VALUES(data), expiry = VALUES(expiry)
        ");
        return $stmt->execute([$id, $data, $expiry]);
    }

    public function destroy($id) {
        return $this->pdo->prepare("DELETE FROM sessions WHERE id = ?")->execute([$id]);
    }

    public function gc($maxlifetime) {
        return $this->pdo->prepare("DELETE FROM sessions WHERE expiry < ?")->execute([time()]);
    }
}

// 註冊
$handler = new DbSessionHandler($pdo);
session_set_save_handler($handler, true); // true = 關閉舊 handler
session_start();
?>

資料表結構:

CREATE TABLE sessions (
    id VARCHAR(128) PRIMARY KEY,
    data TEXT NOT NULL,
    expiry INT UNSIGNED NOT NULL,
    INDEX idx_expiry (expiry)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

安全性考量

  • Session Fixation 攻擊:登入/權限變更時呼叫 session_regenerate_id(true) 產生新 ID。
  • HTTPS 必備:session.cookie_secure = 1、session.cookie_httponly = 1、session.use_only_cookies = 1。
  • 長期 Session 風險:裝置遺失、公用電腦未登出 → 敏感系統建議改用「記住我」長效 Token (獨立資料表、可撤銷),而非無限期 Session。

總結建議

  1. 有主機權限 → 改 php.ini 最簡單徹底。
  2. 無權限 → 程式碼 ini_set + setcookie 覆蓋。
  3. 叢集/高流量/需精確控制 → 資料庫/Redis Session Handler。
  4. 高安全系統 → 放棄「永不過期」,改用可撤銷的 Remember-Me Token。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved