PHP Cookie 安全属性SameSite

wen PHP项目 2

PHP Cookie 的 SameSite 属性详解

什么是 SameSite 属性

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

PHP Cookie 安全属性SameSite

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 银行、支付等高风险场景
单点登录(跨域) LaxNone 子域共享用 Lax,完全跨域用 None
OAuth 认证 Lax 防止常见的 CSRF 攻击
第三方嵌入内容 None 需配合 Secure 和 HTTPS

注意事项

  1. SameSite=None 必须配合 Secure:并且需要 HTTPS 才能正常工作
  2. 浏览器支持:现代浏览器都支持,旧浏览器会忽略该属性
  3. 影响: 使用 Strict 可能会影响用户体验,如支付回调
  4. 测试:使用浏览器开发者工具查看实际发送的 Cookie 头
  5. Cookie 前缀:还可以使用 __Host-__Secure- 前缀加强安全

调试方法

// 查看响应头中的 Cookie
// 在浏览器开发者工具 -> Network -> 查看响应头
// 或者在 PHP 中查看
header_remove(); // 清除所有头信息
echo '<pre>';
print_r(headers_list()); // 查看所有头信息

最佳实践建议

  1. 默认使用 Lax,不要设置成 None 除非确有必要
  2. 始终设置 HttpOnly,防止 XSS 窃取 Cookie
  3. 始终设置 Secure,确保只在 HTTPS 下传输
  4. 合理设置过期时间,不要过长
  5. 使用 PHP 7.3+ 的数组参数,代码更清晰
  6. 定期审计 Cookie 的使用和配置

通过合理配置 SameSite 属性,可以有效提升应用的安全性,同时保持良好用户体验。

抱歉,评论功能暂时关闭!