PHP 子域名 cookie 怎么设

wen PHP项目 1

本文目录导读:

PHP 子域名 cookie 怎么设

  1. 📚 目录导读
  2. 为什么子域名Cookie让人头疼?
  3. 核心参数:domain 属性的正确打开方式
  4. 实战代码:三步设置跨子域共享Cookie
  5. 安全雷区:HttpOnly、Secure 与 SameSite 的“黄金搭配”
  6. 登录态互通与注销:一台服务器管理多个子站
  7. 常见故障排查:为什么我设置了却无效?
  8. 高频问答:开发者最纠结的5个问题

PHP 跨子域名Cookie设置全攻略:从入门到生产环境踩坑指南**


📚 目录导读

  1. 为什么子域名Cookie让人头疼?—— 同源策略与Cookie作用域
  2. 核心参数:domain 属性的正确打开方式
  3. 实战代码:三步设置跨子域共享Cookie
  4. 安全雷区:HttpOnly、Secure 与 SameSite 的“黄金搭配”
  5. 登录态互通与注销:一台服务器管理多个子站
  6. 常见故障排查:为什么我设置了却无效?
  7. 高频问答:开发者最纠结的5个问题

为什么子域名Cookie让人头疼?

当你拥有 a.example.comb.example.com 两个站点,默认情况下浏览器将两者视为完全隔离的源(Origin),PHP 的 setcookie() 函数如果不指定 domain 参数,Cookie 默认绑定在当前完整主机名上(如 a.example.com),导致 b.example.com 无法读取,这并非 PHP 的缺陷,而是浏览器出于隐私保护实施的同源策略(Same-Origin Policy)。

核心逻辑:Cookie 的路径(Path)控制目录范围,而 Domain 属性控制主机名作用域,要实现子域共享,必须将 Domain 设为 .example.com(注意前导点,代表允许所有子域及根域)。

核心参数:domain 属性的正确打开方式

在 PHP 中,setcookie 函数的签名如下:

setcookie(string $name, string $value = "", array $options = [])

关键选项(PHP 7.3+ 推荐使用数组形式):

  • domain:必须设置为 .example.com(带点前缀),否则无效。
  • secure:仅通过 HTTPS 传输。
  • httponly:禁止 JavaScript 访问(防 XSS)。
  • samesite:CSRF 防护,建议设为 LaxStrict

注意:如果直接在 a.example.com 下设置 domain = example.com(不带点),部分浏览器(如火狐)会拒绝接受,而 Chrome 则可能自动忽略该参数。规范要求必须带点

实战代码:三步设置跨子域共享Cookie

场景:用户在 login.example.com 登录,需要在 shop.example.comblog.example.com 共享会话。

第一步(登录处理)

// 在 login.example.com 的登录脚本中
setcookie(
    'auth_token',
    '加密后的用户标识',
    [
        'expires' => time() + 86400 * 7, // 7天有效
        'path' => '/',
        'domain' => '.example.com',      // 关键:带点
        'secure' => true,                // 若全站HTTPS
        'httponly' => true,
        'samesite' => 'Lax'
    ]
);

第二步(跨子域读取): 在任何子域(如 shop.example.com)的 PHP 脚本中,通过 $_COOKIE['auth_token'] 直接读取,无需额外配置。

第三步(安全删除)

setcookie('auth_token', '', time() - 3600, '/', '.example.com');

安全雷区:HttpOnly、Secure 与 SameSite 的“黄金搭配”

  • 绝对要加 HttpOnly:防止黑客通过 XSS 窃取 Cookie,若子域中存在未修复的脚本漏洞,攻击面会扩散至所有共享该 Cookie 的站点。
  • Secure 必须开启:若你启用了 HTTP 与 HTTPS 混合访问,浏览器可能通过 HTTP 明文发送 Cookie,被中间人截获。
  • SameSite=Lax:如果你有跨站跳转需求(如从 a.example.com 通过链接跳转到 b.example.com 并携带 Cookie),Strict 会阻断这种场景。Lax 保留 GET 请求携带,安全性够用。
  • 子域信任边界:共享 Cookie 意味着任何一个子域被入侵,其他子域安全一同沦陷,如果子域间信任级别不同(如 dev.example.com 与生产环境),切勿共享域

登录态互通与注销:一台服务器管理多个子站

推荐架构:使用 中央认证服务器(CAS),所有子域重定向到 login.example.com,验证通过后设置上述 Cookie,其他子域仅需解密 Cookie 信息,无需再次拉取用户表。

注销逻辑: 必须同时销毁所有子域的 Cookie,最稳妥方案是调用统一注销接口:

// 在所有子域的注销脚本中执行
setcookie('auth_token', '', time() - 3600, '/', '.example.com');
destroySession(); // 同时清理session文件

常见故障排查:为什么我设置了却无效?

症状 原因排查
Chrome 能设置,Safari 失效 Domain 未加前导点 ,或本地测试使用了 localhost(应配置虚拟主机为 sub.example.com
设置成功但跨子域读不到 检查 path 是否设为 (默认当前目录)
Cookie 被浏览器拒绝 服务器时间偏差过大,或 expires 格式错误(应使用 Unix 时间戳)
HTTPS 页面无法获取 secure 参数为 true,但页面通过 HTTP 访问
子域间无法同步 检查 cloudflare/Nginx 是否写了 Set-Cookie 头的 domain 覆盖逻辑

高频问答:开发者最纠结的5个问题

Q1:domain 不加点,为什么 Chrome 也能工作? Chrome 对 domain=example.comdomain=.example.com 的解析不严格区分,但 Firefox 严格遵循 RFC 6265,要求必须带点,为确保通用性,务必加前导点。

Q2:如果子域名是 shop.example.com.cn,怎么设置? 应设为 .example.com.cn,即注册根域(如 com.cn)的下一级。不要设为 .com.cn,否则所有以 com.cn 结尾的站点都能读取(严重安全漏洞)。

Q3:能否用 JS 设置跨子域 Cookie? 可以,但会暴露给 XSS,前端设置时需指定 domain=.example.com,且必须用 document.cookie 拼接字符串。强烈建议后端设置,否则 setcookieHttpOnly 功能失效。

Q4:设置了永久的 auth_token,但用户换台电脑就无法登录? 跨子域 Cookie 与设备绑定无关,问题通常出在 Token 存储不在服务端,应在 Redis/MySQL 存储该 Token 的会话标识,而非将明文用户信息直接放进 Cookie。

Q5:子域使用不同端口(如 a.example.com:8080),Cookie 能共享吗? 端口不参与 Cookie 作用域判断,只要主机名一致(a.example.coma.example.com:8080),共享正常,但 a.example.comb.example.com 则必须按上文配置。


通过上述配置与排查,你的 PHP 应用即可在多个子域间无缝共享用户登录状态,最后再强调一次:域名的前导点、SecureSameSite 这三点是生产环境的生死线,请务必在测试环境用 Safari 与 Firefox 交叉验证。

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