PHP Cookie 的 SameSite 属性详解
什么是 SameSite 属性
SameSite 是 Cookie 的一个安全属性,用于控制 Cookie 在跨站请求中是否会被发送,它主要用来防范 CSRF(跨站请求伪造) 攻击。

SameSite 的三个值
Strict(最严格)
- Cookie 只在同站请求中发送
- 完全阻止跨站请求携带 Cookie
- 用户体验可能受影响(如从外部链接进入时无法识别登录状态)
// PHP 7.3+ 方式
setcookie('session_id', $value, [
'expires' => time() + 86400,
'path' => '/',
'domain' => 'example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
]);
Lax(默认,推荐)
- 允许部分跨站请求携带 Cookie
- 安全的跨站请求(GET、HEAD、OPTIONS)会携带
- 不安全的跨站请求(POST、PUT、DELETE)不会携带
- 平衡了安全性和用户体验
// PHP 7.3+ 方式
setcookie('session_id', $value, [
'expires' => time() + 86400,
'path' => '/',
'domain' => 'example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax'
]);
None(不安全)
- 所有跨站请求都会携带 Cookie
- 必须与
Secure属性同时使用 - 仅适用于需要跨站共享 Cookie 的场景
// PHP 7.3+ 方式(需要 HTTPS)
setcookie('session_id', $value, [
'expires' => time() + 86400,
'path' => '/',
'domain' => 'example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'None'
]);
PHP 版本兼容性
PHP 7.3+ 推荐方式
// 使用数组参数,支持所有属性
setcookie('name', 'value', [
'expires' => time() + 3600,
'path' => '/',
'domain' => '.example.com',
'secure' => true, // 仅 HTTPS 发送
'httponly' => true, // 禁止 JS 访问
'samesite' => 'Lax' // SameSite 属性
]);
PHP 7.2 及以下版本
// 使用 header() 函数手动设置
setcookie('name', 'value', time() + 3600, '/; SameSite=Lax', '.example.com', true, true);
// 或者使用 header()
header('Set-Cookie: name=value; expires=' . gmdate('D, d-M-Y H:i:s \G\M\T', time() + 3600) . '; path=/; domain=.example.com; secure; HttpOnly; SameSite=Lax');
完整的安全 Cookie 设置函数
<?php
/**
* 安全地设置 Cookie
*
* @param string $name Cookie 名称
* @param string $value Cookie 值
* @param int $expire 过期时间(秒,默认 1 小时)
* @param string $path 路径
* @param string $domain 域名
* @param string $samesite SameSite 值(Strict/Lax/None)
* @return bool
*/
function setSecureCookie($name, $value, $expire = 3600, $path = '/', $domain = '', $samesite = 'Lax') {
$options = [
'expires' => time() + $expire,
'path' => $path,
'domain' => $domain,
'secure' => isset($_SERVER['HTTPS']), // 自动检测 HTTPS
'httponly' => true, // 始终设置 HttpOnly
'samesite' => $samesite
];
// 如果使用 SameSite=None,必须使用 HTTPS
if ($samesite === 'None' && empty($_SERVER['HTTPS'])) {
error_log('SameSite=None cookies require HTTPS');
return false;
}
return setcookie($name, $value, $options);
}
// 使用示例
setSecureCookie('session_id', 'abc123', 3600 * 24, '/', 'example.com', 'Lax');
?>
各场景下的推荐配置
| 场景 | 推荐 SameSite 值 | 说明 |
|---|---|---|
| 常规 Web 应用 | Lax |
默认推荐,平衡安全与体验 |
| 需要严格安全的应用 | Strict |
银行、支付等高风险场景 |
| 单点登录(跨域) | Lax 或 None |
子域共享用 Lax,完全跨域用 None |
| OAuth 认证 | Lax |
防止常见的 CSRF 攻击 |
| 第三方嵌入内容 | None |
需配合 Secure 和 HTTPS |
注意事项
- SameSite=None 必须配合 Secure:并且需要 HTTPS 才能正常工作
- 浏览器支持:现代浏览器都支持,旧浏览器会忽略该属性
- 影响: 使用 Strict 可能会影响用户体验,如支付回调
- 测试:使用浏览器开发者工具查看实际发送的 Cookie 头
- Cookie 前缀:还可以使用
__Host-和__Secure-前缀加强安全
调试方法
// 查看响应头中的 Cookie // 在浏览器开发者工具 -> Network -> 查看响应头 // 或者在 PHP 中查看 header_remove(); // 清除所有头信息 echo '<pre>'; print_r(headers_list()); // 查看所有头信息
最佳实践建议
- 默认使用
Lax,不要设置成None除非确有必要 - 始终设置
HttpOnly,防止 XSS 窃取 Cookie - 始终设置
Secure,确保只在 HTTPS 下传输 - 合理设置过期时间,不要过长
- 使用 PHP 7.3+ 的数组参数,代码更清晰
- 定期审计 Cookie 的使用和配置
通过合理配置 SameSite 属性,可以有效提升应用的安全性,同时保持良好用户体验。