PHP Session 跨域失效的 5 个真实原因(附排查顺序)

34 阅读3分钟

如果你已经搞定了 PHP 的 CORS,
Session 一到跨域就“像没生效一样” ,那你并不孤单。

典型表现只有一句话:

接口能调通,但 Session 每次都是新的。

然后你会开始搜:

  • php session 跨域
  • php session 跨域失效
  • php 跨域请求解决方案
  • php cors 跨域

这篇文章,我不讲概念,
只按真实项目的排查顺序,告诉你 Session 到底是怎么丢的。


一、Session 跨域失败,本质是 Cookie 没带上

PHP Session 能不能用,完全取决于浏览器有没有带 Cookie

浏览器不带 Cookie,
PHP 不管你代码写得多完美,Session 都一定失效。


二、排查顺序一定要对(重点)

下面这 5 个原因
按顺序查,别乱试


原因一:Access-Control-Allow-Origin 用了 *

这是最致命、也是最常见的错误

❌ 错误写法:

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Credentials: true");

浏览器会直接拒绝携带 Cookie

✅ 正确写法:

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

👉 Session 跨域,Origin 必须写死


原因二:前端没开启 credentials(很多人忽略)

就算后端全写对了,
前端不配合,一样白搭

fetch 示例:

fetch(url, {
  credentials: 'include'
});

axios 示例:

axios.get(url, {
  withCredentials: true
});

👉 这一步不写,Cookie 根本不会发。


原因三:Cookie 的 SameSite 属性不对(高频翻车)

现在浏览器默认是:

SameSite=Lax

跨站请求 不会带 Cookie

你必须明确设置:

session_set_cookie_params([
    'samesite' => 'None',
    'secure'   => true
]);

⚠️ 两个隐藏条件:

  • SameSite=None 必须 HTTPS
  • HTTP 环境直接失效

原因四:Cookie 域名不一致

这是很多人看不见、却真实存在的坑

常见错误场景:

  • 前端:www.example.com
  • 接口:api.example.com
  • Cookie 域:默认只绑当前子域

👉 结果:Session 看起来“丢了”。

正确做法:

ini_set('session.cookie_domain', '.example.com');

让 Cookie 在整个主域下生效


原因五:OPTIONS 预检请求没处理

只要你:

  • 跨域
  • 带 Cookie
  • 用 POST / 自定义 Header

浏览器一定会先发 OPTIONS 请求

如果 PHP 没处理:

👉 后续真正的请求根本不会到达。


三、一个完整可跑的 Session 跨域示例

这是一个真实项目可用级别的最小示例。

<?php
$origin = 'https://www.example.com';

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    header("Access-Control-Allow-Origin: $origin");
    header("Access-Control-Allow-Credentials: true");
    header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
    header("Access-Control-Allow-Headers: Content-Type");
    exit;
}

header("Access-Control-Allow-Origin: $origin");
header("Access-Control-Allow-Credentials: true");

session_set_cookie_params([
    'lifetime' => 0,
    'path'     => '/',
    'domain'   => '.example.com',
    'secure'   => true,
    'httponly' => true,
    'samesite' => 'None'
]);

session_start();

$_SESSION['uid'] = 10086;

echo json_encode([
    'session_id' => session_id(),
    'uid' => $_SESSION['uid']
]);

四、phpstudy 环境下,Session 跨域为什么更容易失败?

原因很现实:

1️⃣ 本地没 HTTPS
2️⃣ 用 localhost / 127.0.0.1
3️⃣ Cookie SameSite 直接被浏览器拦

👉 phpstudy 只能验证逻辑,不能完全验证跨域 Cookie


五、什么时候不建议用 Session 跨域?

说句实话:

  • 多域名
  • 多端(H5 / 小程序 / App)
  • 前后端完全分离

👉 Token / JWT 更省心

Session 跨域是可以做,
维护成本很高


六、为什么我强烈建议用“排查顺序”?

因为 Session 跨域:

  • 不是一个点
  • 是一串条件叠加
  • 错一个,全盘失效

按顺序查,比瞎试效率高 10 倍。


PHP Session 跨域失效,
不是 Session 的问题,是 Cookie 的问题。

只要 Cookie 没进浏览器,
Session 一定是“假的”。