为何跨脚本无法访问PHP Session?请求异常问题排查
我有两个PHP脚本:welcome.php和page.php。
welcome.php代码:
session_start(); $_SESSION['test'] = bin2hex(random_bytes(4)); $val = $_SESSION['test']; $reply = ['data'=> $val]; exit (json_encode($reply));
page.php代码:
session_start(); $val = $_POST['test']//this is the value of $_SESSION['test'] in welcome.php if($val === $_SESSION['test']){ echo 'yes'; }
先通过Ajax请求welcome.php获取session的test值,再向page.php发送请求并传递该值,但页面提示“$_SESSION['test']是未定义数组键”,说明session值未被识别,尽管已在welcome.php中设置。已确认能从welcome.php获取到该值,且已设置允许跨源请求的响应头。
更新
检查后发现两次请求使用的session ID不同,于是修改Ajax请求以复用同一session ID:
const id = window.localStorage.getItem("id");//the session id gotten from first ajax request $.ajax({ url:url, method:'post', xhrFields:{ withCredentials:true }, headers: { /*'Content-Type': 'application/json',*/ 'X-CSRF-Token': csrfToken, 'x-session-id':id, }, dataType:'json', data:input, success: function(r){ //updateLoginStatus() if( r.status === 1 ){ props.setIsLogged(true) } else { showAlert(r.msg,"error") } setBtnLoading(false); props.setCsrf(r.token); }, error:function(a){ //console.log(a) setBtnLoading(false) } })
但修改后的Ajax请求无法正常发送;若注释掉header部分,请求可发送但仍使用不同session ID,无法访问之前存储的session值。请问问题出在哪里?
核心问题拆解
- 跨域Session传递失效:PHP默认通过Cookie传递Session ID,跨域请求时浏览器默认不会携带Cookie,导致两次请求Session ID不匹配。
- 自定义头无效+请求失败:PHP不会自动读取
x-session-id头识别Session,且后端CORS配置未允许自定义头,导致请求被拦截。
分步解决办法
1. 修复后端CORS配置(必填)
在两个PHP脚本的session_start()前添加完整的跨域响应头,确保允许携带凭证和自定义头:
// 在session_start()之前添加 header("Access-Control-Allow-Origin: 你的前端域名"); // 必须填具体域名,不能用* header("Access-Control-Allow-Credentials: true"); header("Access-Control-Allow-Methods: POST, GET, OPTIONS"); header("Access-Control-Allow-Headers: Content-Type, X-CSRF-Token, x-session-id"); // 处理浏览器OPTIONS预请求 if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { exit(0); } session_start();
注意:
Access-Control-Allow-Origin设为*会导致浏览器拒绝携带Cookie,必须指定前端的具体域名。
2. 让PHP识别自定义Session ID头
如果坚持用x-session-id传递Session ID,需要在两个PHP脚本的session_start()前手动读取并设置:
// 在session_start()之前添加 if (isset($_SERVER['HTTP_X_SESSION_ID'])) { session_id($_SERVER['HTTP_X_SESSION_ID']); } session_start();
PHP的
session_id()必须在session_start()前调用才能生效。
3. 更简单的方案:用Cookie自动传递Session ID
既然已经设置了withCredentials: true,只要CORS配置正确,浏览器会自动携带Session Cookie,无需手动存储传递:
- 删除Ajax中的
x-session-id头配置 - 确保后端CORS的
Access-Control-Allow-Origin是具体域名,且Access-Control-Allow-Credentials: true - 第一次请求
welcome.php后,浏览器会自动保存PHPSESSID Cookie,后续请求page.php会自动携带
4. 修复page.php的语法错误
你的page.php代码少了分号,会导致脚本执行异常:
// 原代码 $val = $_POST['test']//this is the value of $_SESSION['test'] in welcome.php // 修正后 $val = $_POST['test'];//this is the value of $_SESSION['test'] in welcome.php
验证步骤
- 请求
welcome.php后,在浏览器开发者工具的Application > Cookies中查看是否存在PHPSESSID Cookie - 请求
page.php时,查看Network面板的请求头,确认Cookie中携带了PHPSESSID - 在
page.php中添加调试代码,确认Session ID和内容:
session_start(); var_dump(session_id()); // 打印当前Session ID var_dump($_SESSION); // 查看Session存储的内容
内容的提问来源于stack exchange,提问作者Eduty

