萬盛學電腦網

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

PHP Cookie 安全操作指南:設定、讀取、刪除與防篡改驗證

為什麼需要封裝 Cookie 操作?

原生 setcookie() 與 $_COOKIE 雖然簡單,但缺乏安全機制:值容易被竄改、無完整性驗證、路徑/域名管理分散。本文提供一組封裝函式,內建 MD5 簽名驗證,防止用戶端偽造 Cookie 資料。

核心函式實作

1. 寫入 Cookie:PutCookie()

function PutCookie($key, $value, $kptime = 0, $pa = "/") {
    global $cfg_cookie_encode;
    setcookie($key, $value, time() + $kptime, $pa);
    // 寫入簽名:取前 16 位 MD5,金鑰含伺服器端密鑰 $cfg_cookie_encode
    setcookie($key . '__ckMd5', substr(md5($cfg_cookie_encode . $value), 0, 16), time() + $kptime, $pa);
}

關鍵點:

  • 雙 Cookie 機制:值 + 簽名
  • 簽名包含伺服器端密鑰 $cfg_cookie_encode,用戶端無法偽造
  • 預設路徑 /,全站可用
  • $kptime=0 表示瀏覽器關閉即失效(Session Cookie)

2. 讀取並驗證:GetCookie()

function GetCookie($key) {
    global $cfg_cookie_encode;
    if (!isset($_COOKIE[$key]) || !isset($_COOKIE[$key . '__ckMd5'])) {
        return '';
    }
    // 驗證簽名
    if ($_COOKIE[$key . '__ckMd5'] != substr(md5($cfg_cookie_encode . $_COOKIE[$key]), 0, 16)) {
        return ''; // 簽名不符,資料被竄改
    }
    return $_COOKIE[$key];
}

驗證失敗時回傳空字串,等同於 Cookie 不存在,避免使用到被竄改的資料。

3. 刪除 Cookie:DropCookie()

function DropCookie($key) {
    setcookie($key, '', time() - 360000, "/");
    setcookie($key . '__ckMd5', '', time() - 360000, "/");
}

將過期時間設為過去(360000 秒約 4 天前),瀏覽器會自動刪除。

使用範例

// 設定密鑰(通常放在設定檔)
$cfg_cookie_encode = 'your_secret_key_here';

// 寫入
PutCookie('user_id', 12345, 3600); // 1 小時有效

// 讀取
$uid = GetCookie('user_id');
if ($uid) {
    echo "歡迎回來,用戶 ID:$uid";
} else {
    echo "Cookie 無效或已過期";
}

// 登出時刪除
DropCookie('user_id');

安全性補充建議

  1. 啟用 HttpOnly:防止 XSS 竊取 Cookie(需 PHP 5.2+)
    setcookie($key, $value, $expire, $path, $domain, $secure, true);
  2. HTTPS 環境下設定 Secure 標記:確保 Cookie 僅在加密連線傳輸
  3. 定期輪換 $cfg_cookie_encode:雖會使現有 Cookie 失效,但能限制洩露影響範圍
  4. 敏感資料勿存 Cookie:Session ID、權限標記等應存伺服器端 Session

常見問題

Q: 為何用 substr(md5(...), 0, 16) 而非完整 32 字元?
A: 縮短 Cookie 體積(每個 Cookie 限制 4KB),16 字元(64 bits)對暴力破解已足夠安全。
Q: 簽名能否防止重放攻擊?
A: 不能。此機制只防篡改,不防重放。需配合 Session 或一次性 Token 解決。
copyright © 萬盛學電腦網 all rights reserved