http_build_cookie() 函数用于构建符合 HTTP 标准的 Cookie 字符串。它可以将 Cookie 参数数组转换为 Set-Cookie 请求头所需的格式字符串。
http_build_cookie() 并不是 PHP 内置函数,但我们可以自定义实现这个功能。PHP 内置的 setcookie() 和 setrawcookie() 函数直接设置 Cookie,而本函数用于生成 Cookie 字符串。
http_build_cookie (
array $cookie_params
) : string
参数说明:
| 参数 | 说明 | 必需 | 默认值 |
|---|---|---|---|
$cookie_params |
包含 Cookie 参数的关联数组 | 是 | 无 |
Cookie 参数数组支持的键名:
name - Cookie 名称(必需)value - Cookie 值(必需)expires - 过期时间(时间戳)max-age - 最大生存时间(秒)path - Cookie 的有效路径domain - Cookie 的有效域名secure - 是否仅通过 HTTPS 传输httponly - 是否仅限 HTTP 访问samesite - SameSite 属性(Strict/Lax/None)下面是一个完整的 http_build_cookie() 函数实现:
<?php
/**
* 构建Cookie字符串
*
* @param array $cookie_params Cookie参数数组
* @return string 构建好的Cookie字符串
*/
function http_build_cookie(array $cookie_params): string
{
// 必需参数检查
if (!isset($cookie_params['name']) || !isset($cookie_params['value'])) {
throw new InvalidArgumentException('Cookie name and value are required');
}
$name = $cookie_params['name'];
$value = $cookie_params['value'];
// 验证名称和值
if (!is_string($name) || !is_string($value)) {
throw new InvalidArgumentException('Cookie name and value must be strings');
}
// 构建基础部分
$cookie = urlencode($name) . '=' . urlencode($value);
// 处理过期时间
if (isset($cookie_params['expires'])) {
if (is_numeric($cookie_params['expires'])) {
$expires = (int)$cookie_params['expires'];
} else {
$expires = strtotime($cookie_params['expires']);
}
if ($expires !== false) {
$cookie .= '; expires=' . gmdate('D, d M Y H:i:s T', $expires);
}
}
// 处理max-age
if (isset($cookie_params['max-age']) && is_numeric($cookie_params['max-age'])) {
$cookie .= '; Max-Age=' . (int)$cookie_params['max-age'];
}
// 处理路径
if (isset($cookie_params['path']) && is_string($cookie_params['path'])) {
$cookie .= '; path=' . $cookie_params['path'];
}
// 处理域名
if (isset($cookie_params['domain']) && is_string($cookie_params['domain'])) {
$cookie .= '; domain=' . $cookie_params['domain'];
}
// 处理secure标志
if (!empty($cookie_params['secure'])) {
$cookie .= '; secure';
}
// 处理httponly标志
if (!empty($cookie_params['httponly'])) {
$cookie .= '; HttpOnly';
}
// 处理samesite属性
if (isset($cookie_params['samesite']) && in_array($cookie_params['samesite'], ['Strict', 'Lax', 'None'], true)) {
$cookie .= '; SameSite=' . $cookie_params['samesite'];
// 如果SameSite=None,则必须设置Secure
if ($cookie_params['samesite'] === 'None' && empty($cookie_params['secure'])) {
$cookie .= '; secure';
}
}
return $cookie;
}
?>
http_build_cookie() 函数。您需要在自己的项目中实现或包含此函数。
下面的示例演示如何使用 http_build_cookie() 函数构建基本的 Cookie 字符串。
<?php
// 引入或定义 http_build_cookie 函数
// require_once 'http_build_cookie.php';
// 构建一个简单的会话 Cookie
$simple_cookie = [
'name' => 'session_id',
'value' => 'abc123def456',
'path' => '/',
'httponly' => true
];
$cookie_string = http_build_cookie($simple_cookie);
echo "<h4>生成的 Cookie 字符串:</h4>";
echo "<div class='alert alert-info'>" . htmlspecialchars($cookie_string) . "</div>";
// 在 HTTP 响应头中使用
echo "<h4>在 HTTP 响应头中使用:</h4>";
echo "<div class='alert alert-success'>";
echo "Set-Cookie: " . htmlspecialchars($cookie_string);
echo "</div>";
// 解码查看 Cookie 信息
echo "<h4>Cookie 信息:</h4>";
echo "<ul>";
echo "<li>名称: session_id</li>";
echo "<li>值: abc123def456</li>";
echo "<li>路径: /</li>";
echo "<li>HttpOnly: 是</li>";
echo "</ul>";
?>
下面的示例演示如何使用所有参数构建一个安全的、带有各种属性的 Cookie。
<?php
// 构建一个安全的、功能完整的 Cookie
$secure_cookie = [
'name' => 'auth_token',
'value' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
'expires' => time() + (7 * 24 * 60 * 60), // 7天后过期
'max-age' => 604800, // 7天(秒)
'path' => '/',
'domain' => '.example.com',
'secure' => true, // 仅HTTPS
'httponly' => true, // 仅HTTP访问
'samesite' => 'Strict' // 严格的SameSite策略
];
$cookie_string = http_build_cookie($secure_cookie);
echo "<h4>生成的安全 Cookie 字符串:</h4>";
echo "<div class='alert alert-info' style='word-break: break-all;'>" . htmlspecialchars($cookie_string) . "</div>";
// 展示各个参数的作用
echo "<h4>Cookie 属性说明:</h4>";
echo "<table class='table table-bordered'>";
echo "<thead><tr><th>属性</th><th>值</th><th>说明</th></tr></thead>";
echo "<tbody>";
$attributes = [
['name', 'auth_token', 'Cookie名称'],
['value', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9', 'JWT令牌值'],
['expires', gmdate('Y-m-d H:i:s', time() + 604800), '过期时间(7天后)'],
['max-age', '604800', '最大生存时间(7天)'],
['path', '/', '在整个域名下有效'],
['domain', '.example.com', '在所有子域名下有效'],
['secure', 'true', '仅通过HTTPS传输'],
['httponly', 'true', '禁止JavaScript访问'],
['samesite', 'Strict', '严格的跨站请求限制']
];
foreach ($attributes as $attr) {
echo "<tr><td><code>" . htmlspecialchars($attr[0]) . "</code></td><td>" . htmlspecialchars($attr[1]) . "</td><td>" . htmlspecialchars($attr[2]) . "</td></tr>";
}
echo "</tbody></table>";
// 比较不同SameSite设置
echo "<h4>SameSite 属性比较:</h4>";
echo "<div class='row'>";
echo "<div class='col-md-4'>";
echo "<div class='card'><div class='card-body'>";
echo "<h5 class='card-title'>Strict</h5>";
echo "<p class='card-text'>最严格,完全禁止跨站请求携带Cookie</p>";
echo "</div></div>";
echo "</div>";
echo "<div class='col-md-4'>";
echo "<div class='card'><div class='card-body'>";
echo "<h5 class='card-title'>Lax</h5>";
echo "<p class='card-text'>宽松模式,允许部分安全的跨站请求(默认)</p>";
echo "</div></div>";
echo "</div>";
echo "<div class='col-md-4'>";
echo "<div class='card'><div class='card-body'>";
echo "<h5 class='card-title'>None</h5>";
echo "<p class='card-text'>允许所有跨站请求,必须与Secure一起使用</p>";
echo "</div></div>";
echo "</div>";
echo "</div>";
?>
下面的示例演示如何批量构建多个 Cookie,并设置到 HTTP 响应头中。
<?php
/**
* 批量构建Cookie字符串
*
* @param array $cookies Cookie参数数组的数组
* @return array Cookie字符串数组
*/
function http_build_cookies(array $cookies): array
{
$cookie_strings = [];
foreach ($cookies as $cookie_params) {
try {
$cookie_strings[] = http_build_cookie($cookie_params);
} catch (Exception $e) {
// 记录错误但继续处理其他Cookie
error_log('Failed to build cookie: ' . $e->getMessage());
}
}
return $cookie_strings;
}
// 定义多个Cookie
$cookies = [
[
'name' => 'session_id',
'value' => 'sess_123456789',
'path' => '/',
'httponly' => true,
'samesite' => 'Lax'
],
[
'name' => 'user_prefs',
'value' => 'theme=dark&lang=zh-CN',
'expires' => time() + (365 * 24 * 60 * 60), // 1年后过期
'path' => '/',
'domain' => '.example.com'
],
[
'name' => 'tracking_consent',
'value' => 'accepted',
'path' => '/',
'secure' => true,
'httponly' => false, // 允许JavaScript访问
'samesite' => 'None'
]
];
// 批量构建
$cookie_strings = http_build_cookies($cookies);
echo "<h4>批量生成的 Cookie 字符串:</h4>";
foreach ($cookie_strings as $index => $cookie_string) {
echo "<div class='alert alert-light mb-2' style='word-break: break-all;'>";
echo "<strong>Cookie " . ($index + 1) . ":</strong> " . htmlspecialchars($cookie_string);
echo "</div>";
}
// 模拟设置HTTP响应头
echo "<h4>在HTTP响应头中设置多个Cookie:</h4>";
echo "<div class='alert alert-success'>";
foreach ($cookie_strings as $cookie_string) {
echo "Set-Cookie: " . htmlspecialchars($cookie_string) . "<br>";
}
echo "</div>";
// 显示Cookie统计信息
echo "<h4>Cookie 统计信息:</h4>";
echo "<ul>";
echo "<li>总共构建了 " . count($cookie_strings) . " 个Cookie</li>";
echo "<li>平均长度: " . round(array_sum(array_map('strlen', $cookie_strings)) / count($cookie_strings)) . " 字符</li>";
echo "<li>包含HttpOnly属性的Cookie: " . count(array_filter($cookies, function($c) { return !empty($c['httponly']); })) . " 个</li>";
echo "<li>包含Secure属性的Cookie: " . count(array_filter($cookies, function($c) { return !empty($c['secure']); })) . " 个</li>";
echo "</ul>";
?>
下面的示例演示 http_build_cookie() 与 PHP 内置 setcookie() 函数的区别和联系。
<?php
// 使用 setcookie() 函数设置Cookie
function set_cookie_with_setcookie(array $params): bool
{
return setcookie(
$params['name'],
$params['value'],
$params['expires'] ?? 0,
$params['path'] ?? '',
$params['domain'] ?? '',
!empty($params['secure']),
!empty($params['httponly'])
);
}
// 使用 http_build_cookie() 手动设置Cookie
function set_cookie_manually(array $params): void
{
$cookie_string = http_build_cookie($params);
header('Set-Cookie: ' . $cookie_string, false);
}
// 相同的Cookie参数
$cookie_params = [
'name' => 'test_cookie',
'value' => 'test_value_' . time(),
'expires' => time() + 3600,
'path' => '/',
'secure' => false,
'httponly' => true
];
echo "<h4>方法对比:</h4>";
echo "<table class='table table-bordered'>";
echo "<thead><tr><th>方法</th><th>代码示例</th><th>优点</th><th>缺点</th></tr></thead>";
echo "<tbody>";
$methods = [
[
'setcookie()',
"setcookie('test_cookie', 'test_value', time() + 3600, '/', '', false, true);",
'简单直接,PHP内置支持',
'不能设置SameSite属性,灵活性较低'
],
[
'http_build_cookie() + header()',
"\$cookie = http_build_cookie(\$params);
header('Set-Cookie: ' . \$cookie);",
'完全控制Cookie格式,支持SameSite',
'需要自定义函数,代码稍复杂'
]
];
foreach ($methods as $method) {
echo "<tr>";
echo "<td><code>" . $method[0] . "</code></td>";
echo "<td><small>" . $method[1] . "</small></td>";
echo "<td>" . $method[2] . "</td>";
echo "<td>" . $method[3] . "</td>";
echo "</tr>";
}
echo "</tbody></table>";
// 生成SameSite Cookie的两种方式
echo "<h4>生成带有 SameSite 属性的 Cookie:</h4>";
// PHP 7.3+ 的 setcookie() 支持 SameSite
if (version_compare(PHP_VERSION, '7.3.0', '>=')) {
echo "<p>PHP 7.3+ 的 setcookie() 支持 SameSite 参数:</p>";
echo "<pre><code class='language-php'>setcookie('name', 'value', [
'expires' => time() + 3600,
'path' => '/',
'domain' => 'example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
]);</code></pre>";
} else {
echo "<p class='text-warning'>您的 PHP 版本 (" . PHP_VERSION . ") 不支持 setcookie() 的 SameSite 参数。</p>";
}
echo "<p>使用 http_build_cookie() 总是支持 SameSite:</p>";
echo "<pre><code class='language-php'>\$cookie = http_build_cookie([
'name' => 'name',
'value' => 'value',
'expires' => time() + 3600,
'path' => '/',
'domain' => 'example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
]);
header('Set-Cookie: ' . \$cookie);</code></pre>";
?>
下面的示例演示在实际应用中使用 http_build_cookie() 进行 API 认证和会话管理。
<?php
/**
* 用户登录处理函数
*
* @param string $username 用户名
* @param string $password 密码
* @return array 包含Cookie信息的数组
*/
function handle_user_login($username, $password)
{
// 验证用户凭据(此处为示例,实际应用中应使用安全的验证方式)
$user = authenticate_user($username, $password);
if (!$user) {
throw new Exception('Invalid credentials');
}
// 生成会话令牌
$session_token = bin2hex(random_bytes(32));
$refresh_token = bin2hex(random_bytes(32));
// 存储会话信息(此处为示例,实际应用中应使用数据库)
store_session($user['id'], $session_token, $refresh_token);
// 构建会话Cookie
$session_cookie = [
'name' => 'session_token',
'value' => $session_token,
'expires' => time() + (24 * 60 * 60), // 24小时
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
];
// 构建刷新令牌Cookie(更长的有效期)
$refresh_cookie = [
'name' => 'refresh_token',
'value' => $refresh_token,
'expires' => time() + (7 * 24 * 60 * 60), // 7天
'path' => '/api/auth/refresh',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
];
// 构建用户偏好设置Cookie
$prefs_cookie = [
'name' => 'user_preferences',
'value' => json_encode([
'theme' => 'dark',
'language' => 'zh-CN',
'timezone' => 'Asia/Shanghai'
]),
'expires' => time() + (365 * 24 * 60 * 60), // 1年
'path' => '/',
'secure' => true,
'httponly' => false, // 允许JavaScript访问
'samesite' => 'Lax'
];
return [
'session' => http_build_cookie($session_cookie),
'refresh' => http_build_cookie($refresh_cookie),
'preferences' => http_build_cookie($prefs_cookie)
];
}
/**
* 设置登录响应头
*
* @param array $cookies Cookie字符串数组
*/
function send_login_response(array $cookies)
{
// 设置HTTP状态码
http_response_code(200);
// 设置Content-Type
header('Content-Type: application/json');
// 设置多个Cookie
foreach ($cookies as $cookie_string) {
header('Set-Cookie: ' . $cookie_string, false);
}
// 返回JSON响应
echo json_encode([
'success' => true,
'message' => 'Login successful',
'timestamp' => time()
]);
}
// 模拟用户验证函数
function authenticate_user($username, $password)
{
// 这里应该是实际的验证逻辑
if ($username === 'admin' && $password === 'password123') {
return ['id' => 1, 'username' => 'admin', 'email' => 'admin@example.com'];
}
return false;
}
// 模拟存储会话函数
function store_session($user_id, $session_token, $refresh_token)
{
// 这里应该是实际的存储逻辑
return true;
}
// 示例使用
echo "<h4>用户登录处理示例:</h4>";
try {
// 模拟用户登录
$cookies = handle_user_login('admin', 'password123');
echo "<div class='alert alert-success'>";
echo "<h5>登录成功!生成的Cookie:</h5>";
foreach ($cookies as $type => $cookie_string) {
echo "<div class='mb-2'>";
echo "<strong>" . ucfirst($type) . " Cookie:</strong><br>";
echo "<code style='word-break: break-all; font-size: 0.9em;'>" . htmlspecialchars($cookie_string) . "</code>";
echo "</div>";
}
echo "</div>";
// 显示将会设置的响应头
echo "<h5>将会设置的HTTP响应头:</h5>";
echo "<div class='alert alert-info'>";
foreach ($cookies as $type => $cookie_string) {
echo "Set-Cookie: " . htmlspecialchars($cookie_string) . "<br>";
}
echo "</div>";
} catch (Exception $e) {
echo "<div class='alert alert-danger'>登录失败: " . htmlspecialchars($e->getMessage()) . "</div>";
}
// Cookie安全最佳实践
echo "<h4 class='mt-4'>Cookie安全最佳实践:</h4>";
echo "<ul>";
echo "<li><strong>总是使用HttpOnly</strong>:防止XSS攻击窃取Cookie</li>";
echo "<li><strong>生产环境使用Secure</strong>:仅通过HTTPS传输Cookie</li>";
echo "<li><strong>设置适当的SameSite</strong>:防止CSRF攻击</li>";
echo "<li><strong>合理设置过期时间</strong>:会话Cookie应较短,刷新令牌可较长</li>";
echo "<li><strong>使用强随机令牌</strong>:Cookie值应是不可预测的</li>";
echo "<li><strong>限制路径和域名</strong>:减少Cookie的暴露范围</li>";
echo "</ul>";
?>
http_build_cookie() 不是 PHP 内置函数,需要自定义实现。urlencode() 处理。setcookie() 稍慢,但差异通常不明显。