Cookie 是 HTTP 協議下服務端在客戶端瀏覽器存儲的小型文本數據(≤4KB),隨後續同域請求自動攜帶,實現「無狀態 HTTP」的狀態感知。PHP 通過 setcookie() 發送 Set-Cookie 響應頭,自動將接收到的 Cookie 解析為 $_COOKIE 超全局數組。
setcookie(
string $name,
string $value = "",
int $expires_or_options = 0,
string $path = "",
string $domain = "",
bool $secure = false,
bool $httponly = false
): bool
// PHP 7.3+ 支持選項數組寫法(推薦)
setcookie('name', 'value', [
'expires' => time() + 3600,
'path' => '/',
'domain' => '.example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
| 參數 | 說明 | 注意事項 |
|---|---|---|
name | Cookie 名稱,即鍵名 | 避免使用中文/特殊字符,建議 ASCII 可打印字符 |
value | Cookie 值 | 自動 urlencode,取值時自動 urldecode;勿存敏感明文 |
expires | Unix 時間戳過期時間;0 或省略 = 會話級(瀏覽器關閉失效) | 用 time()+86400*30 表示 30 天;勿用未來固定日期,客戶端時間可能不準 |
path | 生效路徑前綴 | 預設當前腳本目錄;通常設 / 全站生效 |
domain | 生效域名 | 需包含至少兩個點(如 .example.com);不帶點僅當前主機名 |
secure | 僅 HTTPS 傳輸 | 生產環境必開 true |
httponly | JS 不可讀(document.cookie 不可見) | 必開 true,防 XSS 竊取 Session ID |
samesite | 跨站攜帶策略:Strict/Lax/None | Lax 平衡體驗與安全;None 必配合 secure=true |
<?php
// 1. 讀取/解析 Cookie
$cookieName = 'user_track';
$data = $_COOKIE[$cookieName] ?? '';
$parts = explode('|', $data, 4); // name|email|visits|last_visit
if ($data !== '') {
// 老用戶:更新計數與時間
[$name, $email, $visits, $last] = $parts;
$visits = (int)$visits + 1;
$newData = implode('|', [$name, $email, $visits, time()]);
setcookie($cookieName, $newData, [
'expires' => time() + 86400 * 365,
'path' => '/',
'httponly' => true,
'secure' => isset($_SERVER['HTTPS']),
'samesite' => 'Lax',
]);
echo "歡迎回來,$name!第 $visits 次訪問。";
} else {
// 新用戶:引導註冊
echo '<a href="register.php">立即註冊</a>';
}
// register.php 處理邏輯略...
?>
場景:app.example.com 登錄後,需在 shop.example.com 保持登錄態。
// 登錄服務設置 Cookie
setcookie('sid', $sessionId, [
'expires' => time() + 86400 * 30,
'path' => '/',
'domain' => '.example.com', // 關鍵:以點開頭,覆蓋所有子域
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
所有 *.example.com 子域請求自動攜帶此 Cookie。
適用於 example.com 與 another.com 完全不同域。
$token = bin2hex(random_bytes(32)),存入共享存儲header("Location: https://another.com/sso?token=$token")此為簡易 SSO(單點登錄)模型,生產環境建議用成熟協議(OAuth2/OIDC/SAML)。
原文通過 Apache mod_rewrite 將 /-token-/path 重寫為 /path?sessionid=token,再由 PHP 讀取 $_GET['sessionid'] 手動 session_id()。缺點:URL 洩露 Session ID、日誌記錄風險、SEO 不友好、移動端體驗差。現代瀏覽器對第三方 Cookie 限制日益收緊,建議棄用。
hash_hmac('sha256', $data, $secret) 簽名,或 openssl_encrypt() 加密,防篡改SameSite=Lax 以上:緩解 CSRF,關鍵操作再加雙重 Tokensession_regenerate_id(true)path、domain 最小化,減少洩露面| 現象 | 可能原因 | 排查步驟 |
|---|---|---|
| Cookie 不生效 | 1. setcookie() 前有輸出 2. 域/路徑不匹配 3. 瀏覽器阻止第三方 Cookie 4. secure=true 但 HTTP 訪問 | 檢查響應頭 Set-Cookie;開發者工具 Application 面板查看;curl -I 驗證 |
| 跨域不共享 | 1. domain 設置錯誤 2. SameSite=Strict 阻止 3. 瀏覽器第三方 Cookie 策略 | 確認父域語法;嘗試 Lax/None+Secure;遷移至 SSO 方案 |
| 中文亂碼 | 值未 urlencode 或雙重編碼 | PHP 自動編碼/解碼,勿手動 urlencode;存 JSON 時用 json_encode($arr, JSON_UNESCAPED_UNICODE) |
| 無法刪除 | 刪除時 path/domain/secure 必須與設置時完全一致 | 用相同參數 setcookie('name', '', time()-3600, ...) |
Cookie 是 Web 狀態管理的基石,但也是攻擊面重災區。遵循「最小權限、服務端信任、簽名驗證、HTTPS 強制」原則,配合現代 SameSite 屬性,即可在便利與安全間取得平衡。跨域場景優先選父域 Cookie 或標準 SSO 協議,避免陷入 URL 重寫等過時方案。