You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何跨脚本无法访问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值。请问问题出在哪里?


问题分析与解决方案

核心问题拆解

  1. 跨域Session传递失效:PHP默认通过Cookie传递Session ID,跨域请求时浏览器默认不会携带Cookie,导致两次请求Session ID不匹配。
  2. 自定义头无效+请求失败: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

验证步骤

  1. 请求welcome.php后,在浏览器开发者工具的Application > Cookies中查看是否存在PHPSESSID Cookie
  2. 请求page.php时,查看Network面板的请求头,确认Cookie中携带了PHPSESSID
  3. 在page.php中添加调试代码,确认Session ID和内容:
session_start();
var_dump(session_id()); // 打印当前Session ID
var_dump($_SESSION); // 查看Session存储的内容

内容的提问来源于stack exchange,提问作者Eduty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 05:05:31