PHP 跨域 cookie 共享

wen PHP项目 1

PHP 跨域 Cookie 共享全攻略:从原理到实战的终极指南

目录导读

  1. 跨域 Cookie 的核心痛点 —— 为什么你会在浏览器里“丢失”登录态?
  2. 基础原理拆解 —— SameSite、Domain 属性、CORS 的三角关系
  3. 主流解决方案对比 —— 代理转发、JSONP、CORS + 凭据、iframe + postMessage
  4. PHP 实战代码 —— 三段可运行的跨域共享示例
  5. 安全加固要点 —— 防止 CSRF 与会话固定攻击
  6. 疑难问答 —— 8 个开发者高频提问解答

跨域 Cookie 的核心痛点

当你在 a.example.com 登录后,跳转到 b.example.com 时,浏览器默认不会发送 Cookie,这不是 PHP 的限制,而是浏览器安全策略(Same-Origin Policy)的强制规定,具体表现为:

PHP 跨域 cookie 共享

  • document.cookie 无法读取跨域站点的存储
  • XMLHttpRequestfetch 默认拒绝携带 Cookie
  • 即使服务端设置了 Set-Cookie,浏览器也可能拒绝存储

典型场景:主站 www.shop.com 与支付子站 pay.shop.com 需要共享用户登录态,但 PHP 的 $_COOKIE 在子域下完全空白。


基础原理拆解(必读)

1 Cookie 的 Domain 属性

PHP 中设置跨域共享的第一步是明确作用域:

setcookie('token', $value, [
    'expires' => time() + 3600,
    'path' => '/',
    'domain' => '.example.com',   // 关键:点号开头表示所有子域
    'secure' => true,
    'httponly' => true,
    'samesite' => 'None'          // 必须配合 Secure 使用
]);

如果不设置 domain,浏览器会默认将其绑定到当前完整主机名,导致子域无法读取。

2 SameSite 属性的两难

  • SameSite=Lax(默认):仅允许同站请求携带,跨站 GET 导航会发送,但 POST、iframe 等均阻断
  • SameSite=None:必须搭配 Secure,允许跨站携带——这是跨域共享的前提条件

3 CORS 与 Cookie 的联动

仅仅后端设置 Cookie 不够,前端请求还需要:

header('Access-Control-Allow-Origin: https://b.example.com');
header('Access-Control-Allow-Credentials: true');

Allow-Origin 不能为 ,必须指定具体域名,否则浏览器会拒绝携带凭据。


主流解决方案对比

方案 适用场景 缺点
反向代理(Nginx 转发) 主域与子域同源 增加运维复杂度
JSONP 仅限 GET 请求 无法操作 Cookie 写入,不安全
CORS + 凭据 现代浏览器 需完整处理预检请求
iframe + postMessage 老系统兼容 代码侵入性高

推荐:对于纯 PHP 项目,后端 CORS 头 + 前端 withCredentials 是最标准的做法。


PHP 实战代码

1 共享服务端(主站 login.example.com 生成 Cookie)

<?php
// login.php
session_set_cookie_params([
    'lifetime' => 3600,
    'path' => '/',
    'domain' => '.example.com',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'None'
]);
session_start();
$_SESSION['user_id'] = 123;
// 设置跨域头
header('Access-Control-Allow-Origin: https://b.example.com'); // 明确来源
header('Access-Control-Allow-Credentials: true');
header('Content-Type: application/json');
echo json_encode(['status' => 'login_success']);
?>

2 消费端(子站 b.example.com 读取共享)

<?php
// b.example.com/check.php
session_set_cookie_params([
    'domain' => '.example.com',
    'samesite' => 'None',
    'secure' => true
]);
session_start();
if (isset($_SESSION['user_id'])) {
    echo "共享成功,用户ID:" . $_SESSION['user_id'];
} else {
    echo "未获取到会话";
}
?>

3 前端 JS 发送请求(必须带凭据)

// 页面位于 b.example.com
fetch('https://login.example.com/login.php', {
    method: 'POST',
    credentials: 'include',   // 关键!允许携带 Cookie
    headers: { 'Content-Type': 'application/json' }
}).then(res => res.json())
  .then(data => console.log(data));

安全加固要点

  1. 强制 HTTPSSameSite=None 必须与 Secure 共存,否则 Chrome 直接拒绝
  2. CSRF 令牌:跨域接口增加 X-CSRF-Token 自定义头,PHP 端验证
  3. 防会话固定:登录成功后立即 session_regenerate_id(true)
  4. 限定域名白名单
    $allowed_origins = ['https://b.example.com', 'https://c.example.com'];
    if (in_array($_SERVER['HTTP_ORIGIN'] ?? '', $allowed_origins)) {
     header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
    }
  5. Cookie 指纹绑定:保存用户 IP + User-Agent 的 hash,跨域调用时校验

疑难问答(Q&A)

Q1:为什么设置了 domain=.example.com 子域还是读不到 Cookie? A:检查浏览器是否支持 SameSite=None(Chrome 80+ 要求 Secure),并确认主站和子站都是 HTTPS。session_set_cookie_params 必须在 session_start() 之前调用。

*Q2:Access-Control-Allow-Origin 可以设为 `吗?** A:不可以,与credentials: include冲突,浏览器会报错,必须显式指定具体域名,或动态获取$_SERVER['HTTP_ORIGIN']` 并匹配白名单。

Q3:跨域时 $_SESSION 失效怎么办? A:确认 PHP 的 session.cookie_domain 已在 php.ini 中设置为 .example.com,或者每次请求都手动执行 session_set_cookie_params

Q4:如果子域和主域完全无关(如 a.comb.com),如何共享? A:纯 PHP 无法直接实现,必须采用 SSO(单点登录) 模式,中间有一个认证中心(如 login.com)签发 token,各站点通过重定向传递,不依赖 Cookie domain。

Q5:移动端 App 与 Web 跨域共享 Cookie 可行吗? A:原生 App 不维护浏览器 Cookie 引擎,建议改用 Authorization Header 传递 token,而非 Cookie。

Q6:Safari 默认阻止第三方 Cookie,怎么办? A:Safari 14+ 对跨站 Cookie 限制较严,你可以尝试:

  • 将共享域改为 SameSite=Lax 并在主域下引入 iframe 设置 Cookie
  • 或者使用 Storage Access API(需要用户交互授权)

Q7:为什么预检请求(OPTIONS)不返回 Cookie? A:预检请求本身不应携带 Cookie(浏览器行为),但服务端需要在 OPTIONS 响应中带上 Access-Control-Allow-Credentials: true 和具体的 Allow-Origin

Q8:Nginx 反向代理能否简化跨域 Cookie? A:可以,Nginx 将 b.example.com 的请求代理到 login.example.com,只要上游响应头正确,浏览器看到的仍是同源,Cookie 自然共享。


总结建议

跨域 Cookie 共享的核心是 “三管齐下”:服务端设置 domain + samesite=None + secure,输出正确的 CORS 头,前端请求携带 withCredentials,对于复杂业务,优先考虑使用 JWT + localStorage 替代 Cookie 方案,彻底避免跨域问题,但若必须沿用 Cookie 登录态,请严格遵循上述安全规范,并针对不同浏览器特性做好降级处理。

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