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

PHP Session 機制深度解析:原理、操作與最佳實踐

     編輯:PHP 相關知識

什麼是 Session?

Session(階段作業)是伺服器端儲存使用者狀態資料的機制。當訪客進入網站時建立 Session,離開或逾時則銷毀。與 Cookie 儲存於瀏覽器不同,Session 資料儲存在伺服器(預設為檔案,可擴展為資料庫、Redis、Memcached),僅透過 Session ID(通常存於 Cookie)識別使用者。

PHP 4/5/7/8 Session 運作流程

  1. session_start() 啟動或恢復 Session
  2. 從 Cookie(預設 PHPSESSID)或 URL 參數取得 Session ID
  3. 若找不到有效 Session ID,產生新 ID 並建立儲存檔案
  4. 將 $_SESSION 超全域陣列載入記憶體
  5. 腳本結束時自動序列化寫回儲存介質

核心函式與操作

啟動與基本操作

<?php
// 必須在輸出任何內容前呼叫
session_start();

// 註冊變數(PHP 4 風格,已棄用)
// session_register("username");

// 現代寫法:直接操作 $_SESSION 陣列
$_SESSION['username'] = 'john_doe';
$_SESSION['login_time'] = time();
$_SESSION['permissions'] = ['read', 'write'];

// 讀取
echo $_SESSION['username'];

// 刪除單一變數
unset($_SESSION['permissions']);

// 銷毀整個 Session
session_destroy(); // 刪除伺服器端資料
// 建議同時清除 Cookie
if (ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
}
?>

重要設定參數(php.ini)

參數預設值建議值說明
session.save_handlerfilesredis/memcached儲存介質,分散式系統必改
session.save_path/tmp/var/lib/php/sessions檔案儲存路徑,需權限 600
session.gc_maxlifetime14401800~7200垃圾回收最大壽命(秒)
session.cookie_httponlyOffOn防止 JavaScript 存取 Cookie(防 XSS)
session.cookie_secureOffOn (HTTPS)僅 HTTPS 傳輸 Cookie
session.use_strict_modeOffOn拒絕未初始化的 Session ID
session.sid_length3248Session ID 長度,越長越安全

Session vs Cookie 比較

特性SessionCookie
儲存位置伺服器端客戶端瀏覽器
資料大小限制受限於伺服器記憶體/硬碟約 4KB
安全性較高(資料不外露)較低(可被竄改、側錄)
跨網域共享需共享儲存介質可設定 domain 共享
適用場景敏感資料、大量資料、購物車偏好設定、追蹤、Remember Me

常見應用場景:購物車實作

<?php
session_start();

function addToCart($productId, $quantity = 1) {
    if (!isset($_SESSION['cart'])) {
        $_SESSION['cart'] = [];
    }
    
    if (isset($_SESSION['cart'][$productId])) {
        $_SESSION['cart'][$productId] += $quantity;
    } else {
        $_SESSION['cart'][$productId] = $quantity;
    }
}

function getCartTotal() {
    $total = 0;
    if (!empty($_SESSION['cart'])) {
        // 假設從資料庫取得價格
        foreach ($_SESSION['cart'] as $pid => $qty) {
            $price = getProductPrice($pid); // 自訂函式
            $total += $price * $qty;
        }
    }
    return $total;
}

// 使用範例
addToCart(101, 2);
addToCart(105, 1);
echo "購物車總金額:$" . getCartTotal();
?>

進階主題

自訂 Session 儲存處理器(資料庫範例)

<?php
class DatabaseSessionHandler 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($sessionId) {
        $stmt = $this->pdo->prepare("SELECT data FROM sessions WHERE id = ? AND expiry > ?");
        $stmt->execute([$sessionId, time()]);
        return $stmt->fetchColumn() ?: '';
    }
    
    public function write($sessionId, $data) {
        $expiry = time() + ini_get('session.gc_maxlifetime');
        $stmt = $this->pdo->prepare("INSERT INTO sessions (id, data, expiry) VALUES (?, ?, ?)
                                     ON DUPLICATE KEY UPDATE data = ?, expiry = ?");
        return $stmt->execute([$sessionId, $data, $expiry, $data, $expiry]);
    }
    
    public function destroy($sessionId) {
        $stmt = $this->pdo->prepare("DELETE FROM sessions WHERE id = ?");
        return $stmt->execute([$sessionId]);
    }
    
    public function gc($maxLifetime) {
        $stmt = $this->pdo->prepare("DELETE FROM sessions WHERE expiry < ?");
        return $stmt->execute([time()]);
    }
}

// 註冊自訂處理器
$handler = new DatabaseSessionHandler($pdo);
session_set_save_handler($handler, true);
session_start();
?>

Session 固定攻擊防範

  • 啟用 session.use_strict_mode = On
  • 登入後重新產生 Session ID:session_regenerate_id(true)
  • 驗證 User-Agent、IP 一致性(需權衡行動裝置切換網路情況)

效能優化建議

  1. **避免過大 Session 資料**:僅存放必要識別資訊,大型資料用快取
  2. **分散式部署共享 Session**:使用 Redis Cluster、Memcached、資料庫
  3. **調整 gc 機制**:高流量網站避免檔案系統 inode 耗盡,改用資料庫/Redis
  4. **非同步寫入**:PHP 7+ 支援 session_write_close() 提早釋放鎖定

總結

Session 是 PHP 開發維持狀態的核心機制。正確理解其運作原理、配置安全參數、選擇適合架構的儲存介質,能構建安全、高效能的 Web 應用程式。現代開發建議搭配框架(Laravel、Symfony)內建的 Session 管理元件,享受更完善的封裝與安全防護。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved