PHP 怎么PHP分区Cookie

wen PHP项目 2

本文目录导读:

PHP 怎么PHP分区Cookie

  1. 什么是分区 Cookie?
  2. PHP 中设置分区 Cookie
  3. 验证 Cookie 是否正确设置
  4. 读取分区 Cookie
  5. 删除分区 Cookie
  6. 使用场景
  7. 注意事项与坑
  8. 完整示例(实际使用)

在 PHP 中,分区 Cookie(Partitioned Cookie) 是一种通过 Partitioned 属性实现的 Cookie 隔离机制。

这是为了解决第三方 Cookie 被浏览器逐步禁用后,跨站资源(如嵌入的 iframe)无法保持登录状态的问题。


什么是分区 Cookie?

  • 传统 Cookie:按域名存储,一个网站总能读取自己域名的 Cookie。
  • 分区 Cookie:在传统域名基础上,额外加上顶级站点(Top-Level Site)作为存储分区
  • 浏览器为每个顶级站点维护一个独立的 Cookie 存储槽。

简单说:example.com 的 Cookie 在 a.comb.com 下是彼此隔离的,即使它们都访问 example.com 的资源。


PHP 中设置分区 Cookie

PHP 的 setcookie() 函数从 PHP 7.3 开始支持 samesite 数组参数,但 Partitioned 属性是较新的功能,需要:

  • PHP 7.3+(需要手动拼装)
  • PHP 8.x(原生支持)

使用 setcookie() 的 options 数组(推荐)

<?php
// 传统方式(PHP 7.3+)
setcookie('session_id', 'abc123', [
    'expires'  => time() + 3600,
    'path'     => '/',
    'domain'   => 'example.com',      // 你的域名
    'secure'   => true,                // 必须 HTTPS
    'httponly' => true,
    'samesite' => 'None',              // 必须为 None
    'partitioned' => true              // 📌 启用分区
]);
?>

注意:PHP 8.0 的 setcookie() 还没有 partitioned 参数,需要通过 Header 方式手动设置。


手动设置 Header(兼容所有 PHP 版本)

<?php
$cookieName  = 'session_id';
$cookieValue = 'abc123';
$expires     = time() + 3600;
$path        = '/';
$domain      = 'example.com';
$secure      = true;
$httponly    = true;
// 拼接完整 Cookie 字符串
$header = sprintf(
    '%s=%s; Expires=%s; Path=%s; Domain=%s; Secure; HttpOnly; SameSite=None; Partitioned',
    $cookieName,
    urlencode($cookieValue),
    gmdate('D, d M Y H:i:s T', $expires),
    $path,
    $domain
);
header("Set-Cookie: $header", false);
?>

使用 PHP 8.2+ 原生支持

<?php
// PHP 8.2+ 直接支持 partitioned 参数
setcookie(
    'session_id',
    'abc123',
    [
        'expires'  => time() + 3600,
        'path'     => '/',
        'domain'   => 'example.com',
        'secure'   => true,
        'httponly' => true,
        'samesite' => 'None',
        'partitioned' => true
    ]
);
?>

验证 Cookie 是否正确设置

在浏览器开发者工具(F12)→ Application → Cookies 中查看:

Name: session_id
Value: abc123
Domain: example.com
Path: /
Expires: ...
Secure: ✅
HttpOnly: ✅
SameSite: None
Partitioned: ✅  ← 必须有这个标记

读取分区 Cookie

读取方式与普通 Cookie 完全一样,PHP 会自动处理分区逻辑:

<?php
if (isset($_COOKIE['session_id'])) {
    echo "Session ID: " . $_COOKIE['session_id'];
} else {
    echo "未找到 Cookie";
}
?>

删除分区 Cookie

<?php
// 设置过期时间为过去的时间即可
setcookie('session_id', '', [
    'expires'  => time() - 3600,
    'path'     => '/',
    'domain'   => 'example.com',
    'secure'   => true,
    'httponly' => true,
    'samesite' => 'None',
    'partitioned' => true
]);
?>

使用场景

场景 是否适合使用 Partitioned
普通网站内部登录状态 ❌ 不需要
嵌入 iframe 的第三方服务(支付、聊天、地图) ✅ 需要
跨站图片/资源加载 ✅ 可能需要
跨域 JS 调用 API ❌ 不适用(需 CORS)

注意事项与坑

问题 说明
必须 HTTPS Partitioned 要求 Secure 属性,必须使用 HTTPS
SameSite=None 必须一起设置 Partitioned 必须与 SameSite=None 配合使用
浏览器兼容性 Chrome 115+、Edge 115+、Firefox 126+ 支持;Safari 部分支持
移动端限制 Android WebView 较旧版本不支持
调试困难 分区 Cookie 在不同站点下是隔离的,调试时需要切换场景

完整示例(实际使用)

<?php
// 设置分区 Cookie
function setPartitionedCookie($name, $value, $expires = 3600) {
    $secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
    $cookieOptions = [
        'expires'  => time() + $expires,
        'path'     => '/',
        'secure'   => $secure,
        'httponly' => true,
        'samesite' => 'None',
        // PHP 8.2+ 支持;旧版本用手动方式
        'partitioned' => true
    ];
    setcookie($name, $value, $cookieOptions);
}
// 使用
setPartitionedCookie('user_token', 'abc123', 86400);
// 读取
if (isset($_COOKIE['user_token'])) {
    $token = $_COOKIE['user_token'];
    // 验证 token...
}
?>

方法 PHP 版本 推荐度
setcookie() + options PHP 8.2+ ⭐⭐⭐ 最简洁
手动 Header 拼接 PHP 7.3+ ⭐⭐⭐ 兼容性最好
Header 手动方式 任意版本 ⭐⭐ 老项目可选

最重要的一点Partitioned 必须搭配 Secure + SameSite=None,否则浏览器会忽略该属性,同时要确保你的服务器支持 HTTPS。

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