萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> PHP 程式設計

徹底理解 PHP Cookie 與 Session 機制:原理、差異、安全性與 Session 存儲深度解析

核心差異一覽

維度CookieSession
存儲位置客戶端(瀏覽器)伺服器端(檔案/資料庫/Redis等)
容量限制單個 ~4KB,域名總計 ~20-50 個受限於伺服器儲存空間
生命週期可設定過期時間,持久化預設瀏覽器關閉失效,可配置 gc_maxlifetime
安全性客戶端可竄改、攔截、XSS 竊取敏感資料不離開伺服器,相對安全
跨域支援受同源策略限制,可設定 domain/path需共享 Session ID(Cookie/URL 重寫)
HTTP 交互每請求自動攜帶僅傳遞 Session ID

Cookie 機制詳解

HTTP 協定層面

# 伺服器發送 Cookie(Response Header)
Set-Cookie: PHPSESSID=abc123; path=/; HttpOnly; Secure; SameSite=Lax
Set-Cookie: user_pref=dark_mode; expires=Wed, 31 Dec 2025 23:59:59 GMT; path=/

# 瀏覽器自動攜帶(Request Header)
Cookie: PHPSESSID=abc123; user_pref=dark_mode

關鍵屬性

  • HttpOnly:禁止 JavaScript 讀取(document.cookie),防 XSS 竊取 Session ID
  • Secure:僅 HTTPS 傳輸
  • SameSite:Strict/Lax/None,防 CSRF
  • Domain/Path:作用範圍控制

Session 機制深度解析

核心流程

  1. 啟動:session_start()
  2. 檢查 ID:讀取 $_COOKIE[session_name()](預設 PHPSESSID)
  3. 有 ID:讀取儲存介質中 sess_ 檔案,反序列化填入 $_SESSION
  4. 無 ID:生成新 ID,建立儲存檔案,發送 Set-Cookie
  5. 腳本結束:序列化 $_SESSION 寫回儲存介質

PHP 原生檔案存儲機制(session.save_handler = files)

; php.ini 關鍵配置
session.save_handler = files
session.save_path = "/var/lib/php/sessions"  ; 或 "N;/path" 分級目錄
session.gc_probability = 1
session.gc_divisor = 1000          ; GC 機率 1/1000
session.gc_maxlifetime = 1440      ; 24 分鐘過期
session.name = PHPSESSID           ; Cookie 名稱
session.cookie_lifetime = 0        ; 0 = 瀏覽器關閉失效
session.cookie_path = /
session.cookie_httponly = 1
session.cookie_secure = 1          ; 僅 HTTPS
session.use_strict_mode = 1        ; 拒絕未初始化的 Session ID

垃圾回收(GC)機制

  • 每次 session_start() 有 gc_probability/gc_divisor 機率觸發
  • 掃描 save_path 所有 sess_* 檔案,檢查 filemtime + gc_maxlifetime < time()
  • 過期檔案 unlink() 刪除
  • 高流量站點:建議 gc_probability = 0,改用 cron 定時腳本清理,避免請求阻塞

自定義存儲處理器(session.save_handler = user)

實作 SessionHandlerInterface 或註冊六個回調:

<?php
class MySessionHandler implements SessionHandlerInterface {
    private $db;
    
    public function __construct(PDO $db) { $this->db = $db; }
    
    public function open($savePath, $sessionName) { return true; }
    public function close() { return true; }
    
    public function read($id) {
        $stmt = $this->db->prepare("SELECT data FROM sessions WHERE id = ? AND expiry > ?");
        $stmt->execute([$id, time()]);
        return $stmt->fetchColumn() ?: '';
    }
    
    public function write($id, $data) {
        $expiry = time() + ini_get('session.gc_maxlifetime');
        $stmt = $this->db->prepare("REPLACE INTO sessions (id, data, expiry) VALUES (?, ?, ?)");
        return $stmt->execute([$id, $data, $expiry]);
    }
    
    public function destroy($id) {
        $stmt = $this->db->prepare("DELETE FROM sessions WHERE id = ?");
        return $stmt->execute([$id]);
    }
    
    public function gc($maxlifetime) {
        $stmt = $this->db->prepare("DELETE FROM sessions WHERE expiry < ?");
        return $stmt->execute([time()]);
    }
}

$handler = new MySessionHandler($pdo);
session_set_save_handler($handler, true);  // true = 註冊關閉函數
session_start();
?>

Session ID 傳遞方式

  1. Cookie(預設):PHPSESSID=abc,最透明
  2. URL 重寫:/page.php?PHPSESSID=abc 或 /page.php;PHPSESSID=abc(session.use_trans_sid=1)
  3. 隱藏表單欄位:<input type="hidden" name="PHPSESSID" value="abc">(舊技術,少用)

常見誤區澄清

誤區:「關閉瀏覽器 Session 就消失了」
真相:Session 檔案仍保留在伺服器,直到 GC 清理。關閉瀏覽器僅刪除會話 Cookie(cookie_lifetime=0),下次訪問無 ID 自然無法關聯舊 Session。若 Cookie 設定 cookie_lifetime > 0 持久化,或手動傳回舊 ID,Session 依然有效。

安全強化清單

  1. ✅ session.use_strict_mode = 1 防 Session Fixation
  2. ✅ session.cookie_httponly = 1 防 XSS 竊取 ID
  3. ✅ session.cookie_secure = 1 僅 HTTPS 傳輸
  4. ✅ session.cookie_samesite = 'Lax' 防 CSRF
  5. ✅ 登入後 session_regenerate_id(true) 重新生成 ID、銷毀舊 Session
  6. ✅ 敏感操作重新驗證密碼/雙因子認證
  7. ✅ 登出時 session_destroy() + setcookie(session_name(), '', time()-3600, '/') 徹底清理

JSESSIONID 與 PHPSESSID 的異同

  • Java (Tomcat/Jetty) 使用 JSESSIONID,PHP 使用 PHPSESSID,本質相同
  • Java Servlet 規範定義 Session 介面,容器實作存儲(記憶體/資料庫/集群)
  • PHP 原生檔案存儲,集群需共享存儲(NFS/Redis/資料庫)
  • 兩者皆支援 URL 重寫備援

總結

Cookie 是客戶端狀態持久化機制,Session 是伺服器端狀態管理機制,Session 通常借助 Cookie 傳遞 ID。理解 HTTP 無狀態本質、Cookie/Session 交互流程、PHP Session 存儲與 GC 機制、安全屬性配置,是構建安全、可擴展 Web 應用的基礎。現代架構建議:Session 資料極小化(僅存用戶 ID、權限標識),業務資料放 Redis/資料庫,Session 存儲統一用 Redis Cluster 實現分布式共享。

copyright © 萬盛學電腦網 all rights reserved