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

PHP Cookie 操作完整指南:設定、讀取、安全屬性與最佳實踐

     編輯:PHP 相關知識

Cookie 是 HTTP 無狀態特性下維持狀態的關鍵機制。本文詳細說明 PHP Cookie 的設定參數、安全屬性、跨域共享、加密簽名與現代替代方案。

基礎操作

設定 Cookie

<?php
// 基本語法:setcookie(name, value, expires, path, domain, secure, httponly)
setcookie('user_id', '12345', [
    'expires' => time() + 86400 * 30, // 30 天
    'path' => '/',
    'domain' => 'example.com',        // 可選,預設為當前域名
    'secure' => true,                 // 僅 HTTPS 傳送
    'httponly' => true,               // JavaScript 無法存取(防 XSS)
    'samesite' => 'Lax'               // CSRF 保護:Lax/Strict/None
]);

// PHP 7.3+ 陣列語法(推薦)
setcookie('session_token', $token, time() + 3600, '/', '', true, true);
// 舊式位置參數:setcookie('name', 'value', expire, path, domain, secure, httponly)
?>

讀取 Cookie

<?php
// $_COOKIE 超全域變數(只包含無 HttpOnly 的 Cookie)
$userId = $_COOKIE['user_id'] ?? null;

// 所有 Cookie(含 HttpOnly)需從標頭解析
$cookies = [];
foreach (explode('; ', $_SERVER['HTTP_COOKIE'] ?? '') as $pair) {
    [$name, $value] = explode('=', $pair, 2) + [null, null];
    if ($name !== null) $cookies[$name] = urldecode($value);
}
?>

刪除 Cookie

<?php
// 設定過期時間為過去
setcookie('user_id', '', [
    'expires' => time() - 3600,
    'path' => '/',
    'domain' => 'example.com',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Lax'
]);
?>

安全屬性深度解析

屬性用途建議值
Secure僅 HTTPS 傳輸true(生產環境必須)
HttpOnly阻擋 JavaScript 存取true(除非前端需讀取)
SameSite跨站請求攜帶控制Lax(平衡安全與體驗),關鍵操作用 Strict
DomainCookie 作用域明確指定,避免過寬
Path路徑範圍/(全站)或特定路徑

跨子域共享 Cookie

<?php
// 主域 example.com,子域 a.example.com, b.example.com
// 設定 Domain 為 .example.com(前綴點)或 example.com(現代瀏覽器相容)
setcookie('shared_token', $token, [
    'expires' => time() + 86400 * 7,
    'path' => '/',
    'domain' => 'example.com', // 不加前綴點,現代瀏覽器包含子域
    'secure' => true,
    'httponly' => true,
    'samesite' => 'None' // 跨子域若為不同站點需 None + Secure
]);
?>

Cookie 加密與簽名(防竄改)

<?php
class SecureCookie {
    private string $secretKey;
    private string $cipher = 'aes-256-gcm';

    public function __construct(string $secretKey) {
        $this->secretKey = $secretKey;
    }

    public function set(string $name, mixed $value, array $options = []): void {
        $payload = json_encode($value, JSON_UNESCAPED_UNICODE);
        $iv = random_bytes(12); // GCM 建議 12 bytes
        $tag = '';
        $encrypted = openssl_encrypt($payload, $this->cipher, $this->secretKey, OPENSSL_RAW_DATA, $iv, $tag);
        $cookieValue = base64_encode($iv . $tag . $encrypted);
        
        setcookie($name, $cookieValue, $options + [
            'httponly' => true,
            'secure' => true,
            'samesite' => 'Lax'
        ]);
    }

    public function get(string $name): mixed {
        $cookieValue = $_COOKIE[$name] ?? null;
        if (!$cookieValue) return null;

        $data = base64_decode($cookieValue, true);
        if (!$data) return null;

        $iv = substr($data, 0, 12);
        $tag = substr($data, 12, 16);
        $encrypted = substr($data, 28);
        
        $decrypted = openssl_decrypt($encrypted, $this->cipher, $this->secretKey, OPENSSL_RAW_DATA, $iv, $tag);
        if ($decrypted === false) return null;

        return json_decode($decrypted, true);
    }
}

// 使用
$cookie = new SecureCookie($_ENV['COOKIE_SECRET']);
$cookie->set('user_prefs', ['theme' => 'dark', 'lang' => 'zh-TW']);
$prefs = $cookie->get('user_prefs');
?>

Session vs Cookie 選擇指南

特性SessionCookie
儲存位置伺服器(檔案/Redis/DB)客戶端瀏覽器
資料大小無實際限制單個 4KB,總計約 300 個
敏感資料適合(不暴露給客戶端)不適合(可被竄改/讀取)
跨伺服器需共享儲存(Redis/DB)天然跨伺服器
生命週期瀏覽器關閉失效(可調整)可設定長期

現代替代方案

  • JWT (JSON Web Token):無狀態認證、攜帶聲明、需妥善保管密鑰
  • LocalStorage/SessionStorage:純客戶端儲存、不自動隨請求發送、容量 5MB+
  • IndexedDB:客戶端資料庫、支援索引查詢、大量資料
  • HTTP 快取標頭:`ETag`、`Last-Modified`、`Cache-Control` 替代部分 Cookie 用途

GDPR/隱私法規合規

<?php
// 1. 取得明確同意後才設定非必要 Cookie
if (isset($_COOKIE['cookie_consent']) && $_COOKIE['cookie_consent'] === 'accepted') {
    setcookie('analytics_id', generateId(), [...]);
}

// 2. 提供撤銷同意機制
if ($_POST['revoke_consent'] ?? false) {
    setcookie('analytics_id', '', ['expires' => time() - 3600, ...]);
    setcookie('cookie_consent', 'revoked', ['expires' => time() + 86400 * 365, ...]);
}

// 3. Cookie 政策頁面說明用途、保存期限、第三方共享
?>

除錯技巧

  • 瀏覽器開發者工具 → Application/Storage → Cookies
  • 檢查 `Set-Cookie` 回應標頭是否正確送達
  • 確認域名/路徑/安全屬性符合預期
  • 使用 `curl -v` 或 Postman 檢查原始標頭

正確使用 Cookie 需兼顧功能、安全與法規。核心原則:敏感資料進 Session/資料庫、最小權限原則設定屬性、加密簽名防竄改、遵循隱私法規取得同意。

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