主域名如何从子域名获取会话信息?Cookie与SessionStorage疑问
问题背景
我知道可以通过以下方式设置跨子域Cookie:
setcookie('info', json_encode(array('foo' => 'bar')), time() + (86400 * 30), "/", ".example.com");
即使代码在www.example.com上运行,react.example.com也能读取该Cookie。
现在我想实现反向操作:让React应用在react.example.com上创建并存储会话信息:
sessionStorage.setItem('react_info', `${user.info}`);
之后通过链接重定向用户到www.example.com的PHP页面,但在该页面执行:
var_dump($_SESSION['react_info']);
结果返回NULL,因为sessionStorage仅在当前子域react.example.com下有效。
请问有哪些解决办法?另外,出于安全考量,为何Cookie可以轻松跨子域共享,而服务器端会话却无法实现?
解决办法
URL参数传递(非敏感数据适用):重定向时把
react_info编码后附加到跳转链接,PHP页面读取后存入会话:const userInfo = sessionStorage.getItem('react_info'); window.location.href = `https://www.example.com/target.php?react_info=${encodeURIComponent(userInfo)}`;PHP端处理:
session_start(); if (isset($_GET['react_info'])) { $_SESSION['react_info'] = urldecode($_GET['react_info']); var_dump($_SESSION['react_info']); }注意:敏感信息别用这种方式,参数会暴露在地址栏和日志中。
跨子域Cookie传递:用Cookie替代
sessionStorage存储信息,设置跨子域属性后,PHP直接读取Cookie并存入会话:const userInfo = `${user.info}`; document.cookie = `react_info=${encodeURIComponent(userInfo)}; path=/; domain=.example.com; max-age=86400; Secure; HttpOnly`;PHP端处理:
session_start(); if (isset($_COOKIE['react_info'])) { $_SESSION['react_info'] = urldecode($_COOKIE['react_info']); var_dump($_SESSION['react_info']); }建议加上
Secure(仅HTTPS传输)、HttpOnly(防止XSS窃取)属性提升安全性。后端API传递(敏感数据首选):React调用
www.example.com的接口提交数据,后端直接存入会话,再跳转页面:const userInfo = sessionStorage.getItem('react_info'); fetch('https://www.example.com/save-session.php', { method: 'POST', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, body: `react_info=${encodeURIComponent(userInfo)}`, credentials: 'include' // 携带跨域Cookie,需后端配置CORS允许 }).then(() => { window.location.href = 'https://www.example.com/target.php'; });接口
save-session.php代码:session_start(); if (isset($_POST['react_info'])) { $_SESSION['react_info'] = urldecode($_POST['react_info']); echo "会话已保存"; }需后端配置CORS,允许
react.example.com的跨域请求。
关于跨子域会话与Cookie的安全差异
Cookie是客户端存储的键值对,跨子域共享是浏览器的可配置行为——只要设置domain=.example.com,浏览器就会在所有.example.com子域的请求中携带该Cookie。但这并不代表Cookie“无风险”,必须配合HttpOnly、Secure、SameSite等属性才能防范XSS、CSRF攻击。
服务器端会话(比如PHP的$_SESSION)本质是服务器存储的会话数据,客户端仅持有一个会话ID(通常存在Cookie里)。会话ID可以通过跨子域Cookie共享,但会话数据绑定在服务器的会话存储上:默认情况下,不同子域的PHP应用会使用独立的本地文件存储会话,所以无法读取彼此的数据。并非“无法实现跨子域共享”,只要让多个子域的PHP应用共享同一个会话存储(比如Redis、数据库),同时会话ID的Cookie设置了跨子域属性,就能实现服务器端会话的跨子域共享。
简单总结:
- Cookie是客户端存储,跨子域靠浏览器规则传递;
- 服务器端会话是服务器存储,跨子域需要额外配置共享存储+跨域会话ID Cookie,默认不共享是出于隔离性的安全设计。
内容的提问来源于stack exchange,提问作者user8411456

