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

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

     編輯:PHP 相關知識

前言

HTTP 是無狀態協定,Cookie 與 Session 是 Web 開發中實現狀態保持的兩大核心機制。本文系統梳理 PHP 中 Cookie 與 Session 的原理差異、操作 API、常見陷阱與安全建議。

一、Cookie:客戶端狀態存儲

1. 核心特點

  • 資料儲存在瀏覽器端(文字檔或資料庫)。
  • 每次請求自動攜帶對應域名/路徑下的 Cookie。
  • 受同源策略限制,跨域不共享。
  • 大小限制約 4KB,數量限制約 20~50 個/域名。

2. 設定 Cookie

<?php
// 基礎語法
bool setcookie(
    string $name,
    string $value = "",
    int $expire = 0,          // Unix 時間戳;0 = 瀏覽器關閉失效
    string $path = "/",       // 生效路徑
    string $domain = "",      // 生效域名(.example.com 含子域名)
    bool $secure = false,     // 僅 HTTPS 傳輸
    bool $httponly = true     // 禁止 JS 存取(防 XSS)
);

// 範例:有效期 1 小時,全站可用,僅 HTTPS+HttpOnly
setcookie('user_id', '12345', time() + 3600, '/', '.example.com', true, true);

// 陣列式寫入(自動序列化為多個 Cookie)
setcookie('pref[theme]', 'dark');
setcookie('pref[lang]', 'zh-TW');
// 讀取時:$_COOKIE['pref']['theme']
?>

3. 讀取與刪除

<?php
// 讀取
$userId = $_COOKIE['user_id'] ?? null;

// 刪除:設定過期時間為過去
setcookie('user_id', '', time() - 3600, '/', '.example.com', true, true);
?>

4. 常見坑點與解決

問題原因解決方案
headers already sent 警告在 setcookie() 前有輸出(空白、BOM、echo)確保無輸出;或啟用 ob_start() 緩衝輸出
中文亂碼Cookie 僅支援 ASCII使用 urlencode() 儲存,urldecode() 讀取
magic_quotes_gpc 自動轉義舊版 PHP 設定PHP 5.4+ 已移除;舊版用 stripslashes() 處理
用戶禁用 Cookie隱私設定/無痕模式檢測並降級提示;或改用 Session + URL 傳遞 SID(不推薦)

二、Session:伺服器端狀態管理

1. 運作原理

  1. 呼叫 session_start(),PHP 檢查請求中是否攜帶 Session ID(預設 Cookie 名 PHPSESSID)。
  2. 若無,生成新 ID,建立伺服器端儲存檔(預設 /tmp),並發送 Set-Cookie 標頭。
  3. 後續請求攜帶 ID,PHP 自動載入對應的 $_SESSION 資料。

2. 基本操作

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

// 寫入
$_SESSION['user'] = ['id' => 1, 'name' => 'Alice'];
$_SESSION['cart'] = [101, 202];

// 讀取
$userName = $_SESSION['user']['name'] ?? 'Guest';

// 刪除單一鍵
unset($_SESSION['cart']);

// 徹底銷毀 Session(登出流程)
$_SESSION = [];                    // 清空陣列
if (ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
);
}
session_destroy(); // 刪除伺服器端儲存檔
?>

3. Session ID 傳遞方式

  • Cookie(預設):最常用、最安全。
  • URL 參數:?PHPSESSID=abc123,僅用於禁用 Cookie 環境,易洩露於日誌/Referer,不推薦。

4. 進階配置

<?php
// 必須在 session_start() 之前設定
ini_set('session.gc_maxlifetime', 7200);      // 垃圾回收壽命(秒)
ini_set('session.cookie_lifetime', 3600);     // Cookie 存活時間
ini_set('session.cookie_httponly', 1);        // 防 XSS
ini_set('session.cookie_secure', 1);          // 僅 HTTPS(生產環境必開)
ini_set('session.use_strict_mode', 1);        // 拒絕未初始化的 ID(防固定攻擊)

// 自訂儲存處理器(資料庫、Redis、Memcached)
session_set_save_handler(
    'open', 'close', 'read', 'write', 'destroy', 'gc'
);
// 或實作 SessionHandlerInterface 介面
?>

三、Cookie vs Session:選型指南

維度CookieSession
儲存位置客戶端伺服器端
容量~4KB受限於伺服器記憶體/磁碟
安全性可被竄改/竊取較安全(ID 若洩露仍可劫持)
適用場景偏好設定、追蹤、記住登入用戶狀態、購物車、權限驗證
生命週期可設定長期通常短期(瀏覽器關閉或 gc_maxlifetime)

四、安全最佳實踐清單

  • ✅ 所有 Session Cookie 設定 HttpOnly、Secure、SameSite=Strict/Lax。
  • ✅ 登入後重新生成 Session ID(session_regenerate_id(true)),防 Session Fixation。
  • ✅ 敏感操作(修改密碼、付款)要求二次驗證或 CSRF Token。
  • ✅ 生產環境使用集中式 Session 儲存(Redis Cluster),支援多伺服器負載均衡。
  • ✅ 定期清理過期 Session,避免檔案系統 inode 耗盡。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved