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 為數組,可一次性設置所有屬性。
| 參數 | 說明 | 示例 |
|---|---|---|
name | Cookie 名稱(必填) | '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 |
<?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
]);
<?php
// 超全局數組 $_COOKIE(自動 URL 解碼)
$userId = $_COOKIE['user_id'] ?? null;
$prefs = json_decode($_COOKIE['user_prefs'] ?? '{}', true);
// 兼容舊版 $HTTP_COOKIE_VARS(已棄用,勿用)
<?php
// 標準刪除:設置過去時間
setcookie('user_id', '', time() - 3600, '/', '.example.com');
// 僅名稱也可刪除(值為空、過期 0)
setcookie('user_id'); // 等同於 setcookie('user_id', '', 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',
],
];
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>
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>
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;
Strict:完全禁止跨站發送,體驗較差(跳轉鏈接不帶 Cookie)。Lax(推薦默認):允許安全的跨站請求(GET 鏈接),平衡安全與體驗。None:跨站發送,必須配合 Secure=true。__Host-:要求 Secure、Path=/、無 Domain,綁定當前 Host。__Secure-:要求 Secure,防止 HTTPS 降級攻擊竄改。setcookie('__Host-session', $token, ['secure'=>true, 'httponly'=>true, 'path'=>'/', 'samesite'=>'Lax']);
<?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;
}
setcookie(),否則會觸發「Headers already sent」警告並失效。HttpOnly=true 防 XSS,Secure=true 強制 HTTPS,SameSite=Lax 防 CSRF——三大屬性缺一不可。掌握 Cookie 全生命周期管理,能構建既安全又友好的用戶認證體驗。建議新項目直接使用成熟框架(Laravel、Symfony、Slim 等)封裝的 Cookie/Session 組件,減少手寫邏輯帶來的安全隱患。