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

PHP Cookie 完整操作指南:設置、讀取、刪除與登錄實戰案例

     編輯:PHP 相關知識

基礎 API:setcookie()

bool setcookie(
    string $name,
    string $value = "",
    int $expires_or_options = 0,
    string $path = "",
    string $domain = "",
    bool $secure = false,
    bool $httponly = false
)

PHP 7.3+ 支持 $expires_or_options 為數組,可一次性設置所有屬性。

核心參數詳解

參數說明示例
nameCookie 名稱(必填)'user_id'
value值,自動 URL 編碼'john_doe'
expires過期時間戳,0=會話級,<0 刪除time()+3600 (1小時)
path生效路徑,/ 全站'/'
domain生效域名,.example.com 含子域'.example.com'
secure僅 HTTPS 傳輸true
httponly禁止 JS 訪問(防 XSS)true

常用操作代碼片段

設置 Cookie

<?php
// 會話級(瀏覽器關閉失效)
setcookie('session_flag', '1');

// 持久化 1 小時
setcookie('remember_me', 'yes', time() + 3600, '/', '.example.com', true, true);

// PHP 7.3+ 數組寫法(推薦,可讀性強)
setcookie('user_prefs', json_encode(['theme' => 'dark']), [
    'expires'  => time() + 86400 * 30,
    'path'     => '/',
    'domain'   => '.example.com',
    'secure'   => true,
    'httponly' => true,
    'samesite' => 'Lax', // 防 CSRF
]);

讀取 Cookie

<?php
// 超全局數組 $_COOKIE(自動 URL 解碼)
$userId = $_COOKIE['user_id'] ?? null;
$prefs  = json_decode($_COOKIE['user_prefs'] ?? '{}', true);

// 兼容舊版 $HTTP_COOKIE_VARS(已棄用,勿用)

刪除 Cookie

<?php
// 標準刪除:設置過去時間
setcookie('user_id', '', time() - 3600, '/', '.example.com');

// 僅名稱也可刪除(值為空、過期 0)
setcookie('user_id'); // 等同於 setcookie('user_id', '', 1);

實戰案例:基於 Cookie 的「記住我」登錄系統

1. 配置文件 config.php

<?php
return [
    'db' => [
        'host' => 'localhost',
        'user' => 'root',
        'pass' => 'secret',
        'name' => 'myapp',
    ],
    'cookie' => [
        'prefix'   => 'myapp_',
        'expire'   => 86400 * 30, // 30 天
        'domain'   => '.example.com',
        'secure'   => true,
        'httponly' => true,
        'samesite' => 'Lax',
    ],
];

2. 登錄處理 login.php

<?php
require 'config.php';
$cfg = require 'config.php';
$pdo = new PDO("mysql:host={$cfg['db']['host']};dbname={$cfg['db']['name']};charset=utf8mb4",
    $cfg['db']['user'], $cfg['db']['pass']);

$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = trim($_POST['username'] ?? '');
    $password = $_POST['password'] ?? '';

    if ($username && $password) {
        $stmt = $pdo->prepare('SELECT id, username, password FROM users WHERE username = ?');
        $stmt->execute([$username]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);

        if ($user && password_verify($password, $user['password'])) {
            // 登錄成功,設置 Cookie
            $cookieCfg = $cfg['cookie'];
            setcookie($cookieCfg['prefix'] . 'uid', $user['id'], time() + $cookieCfg['expire'],
                '/', $cookieCfg['domain'], $cookieCfg['secure'], $cookieCfg['httponly']);
            setcookie($cookieCfg['prefix'] . 'uname', $user['username'], time() + $cookieCfg['expire'],
                '/', $cookieCfg['domain'], $cookieCfg['secure'], $cookieCfg['httponly']);

            header('Location: dashboard.php');
            exit;
        }
        $error = '用戶名或密碼錯誤';
    } else {
        $error = '請填寫完整信息';
    }
}
// 若已有 Cookie 直接跳轉
if (isset($_COOKIE[$cfg['cookie']['prefix'] . 'uid'])) {
    header('Location: dashboard.php');
    exit;
}
?>
<!DOCTYPE html>
<html><body>
<h2>登錄</h2>
<?php if ($error): ?><p style="color:red"><?= htmlspecialchars($error) ?></p><?php endif; ?>
<form method="post">
    <label>用戶名: <input name="username" required></label><br>
    <label>密碼: <input type="password" name="password" required></label><br>
    <button>登錄</button>
</form>
</body></html>

3. 受保護頁面 dashboard.php

<?php
require 'config.php';
$cfg = require 'config.php';
$prefix = $cfg['cookie']['prefix'];

if (empty($_COOKIE[$prefix . 'uid'])) {
    header('Location: login.php');
    exit;
}
?>
<!DOCTYPE html>
<html><body>
<h2>歡迎,<?= htmlspecialchars($_COOKIE[$prefix . 'uname']) ?></h2>
<p>用戶 ID: <?= htmlspecialchars($_COOKIE[$prefix . 'uid']) ?></p>
<a href="logout.php">退出登錄</a>
</body></html>

4. 登出 logout.php

<?php
require 'config.php';
$cfg = require 'config.php';
$prefix = $cfg['cookie']['prefix'];

setcookie($prefix . 'uid',   '', time() - 3600, '/', $cfg['cookie']['domain'], $cfg['cookie']['secure'], $cfg['cookie']['httponly']);
setcookie($prefix . 'uname', '', time() - 3600, '/', $cfg['cookie']['domain'], $cfg['cookie']['secure'], $cfg['cookie']['httponly']);

header('Location: login.php');
exit;

進階主題與最佳實踐

1. SameSite 屬性(防 CSRF)

  • Strict:完全禁止跨站發送,體驗較差(跳轉鏈接不帶 Cookie)。
  • Lax(推薦默認):允許安全的跨站請求(GET 鏈接),平衡安全與體驗。
  • None:跨站發送,必須配合 Secure=true。

2. Cookie 前綴(安全增強)

  • __Host-:要求 Secure、Path=/、無 Domain,綁定當前 Host。
  • __Secure-:要求 Secure,防止 HTTPS 降級攻擊竄改。
setcookie('__Host-session', $token, ['secure'=>true, 'httponly'=>true, 'path'=>'/', 'samesite'=>'Lax']);

3. 加密簽名 Cookie(防篡改)

<?php
function setSignedCookie($name, $value, $secret, $expire = 0)
{
    $payload = json_encode(['v' => $value, 'e' => $expire ? time() + $expire : 0]);
    $sig = hash_hmac('sha256', $payload, $secret);
    setcookie($name, base64_encode($payload . '.' . $sig), $expire, '/', '', true, true);
}

function getSignedCookie($name, $secret)
{
    $cookie = $_COOKIE[$name] ?? '';
    [$payload, $sig] = explode('.', base64_decode($cookie), 2) + ['', ''];
    if (hash_equals(hash_hmac('sha256', $payload, $secret), $sig)) {
        $data = json_decode($payload, true);
        if ($data && (!$data['e'] || $data['e'] > time())) {
            return $data['v'];
        }
    }
    return null;
}

4. 關鍵提醒

  1. 必須在任何輸出前調用 setcookie(),否則會觸發「Headers already sent」警告並失效。
  2. Cookie 大小限制 4KB,不宜存放大量數據;大數據請用 Session + 數據庫/Redis。
  3. 敏感信息(密碼、Token)勿直接存 Cookie,應存加密 ID 或簽名 Token,服務端驗證映射。
  4. 設置 HttpOnly=true 防 XSS,Secure=true 強制 HTTPS,SameSite=Lax 防 CSRF——三大屬性缺一不可。

掌握 Cookie 全生命周期管理,能構建既安全又友好的用戶認證體驗。建議新項目直接使用成熟框架(Laravel、Symfony、Slim 等)封裝的 Cookie/Session 組件,減少手寫邏輯帶來的安全隱患。

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