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

Azure AD OAuth2 POST方式SSO登录PHP会话丢失问题排查

问题:Azure AD OAuth2 POST登录后SESSION变量为空

我编写了基于Azure AD的OAuth2 POST方式SSO登录PHP代码,登录流程可正常运行,但重定向到welcome.php页面后,会话(session)变量全部为空。以下为参考代码:

$appid = "xxxxxxxxxxxx"; //(MASKING DATA FOR OBVIOUS REASONS)

$tenantid = "xxxxxxxxxxxx"; //(MASKING DATA FOR OBVIOUS REASONS)

$secret = "xxxxxxxxxxxx"; //(MASKING DATA FOR OBVIOUS REASONS)

$login_url = "https://login.microsoftonline.com/" . $tenantid . "/oauth2/v2.0/authorize";

session_start();
$_SESSION['state'] = session_id();
echo "MS OAuth2.0 Demo ";
if (isset($_SESSION['msatg'])) {
    echo "Authenticated " . $_SESSION["uname"] . "  ";
    echo 'Log Out';
} else {
    echo 'You can Log In with Microsoft';
}

if (isset($_GET['action']) && $_GET['action'] == 'login') {
    $params = array('client_id' => $appid, 'redirect_uri' => 'https://abc.xyz.com/sso/', 'response_type' => 'token', 'response_mode' => 'form_post', 'scope' => 'https://graph.microsoft.com/User.Read', 'state' => $_SESSION['state']);
    header('Location: ' . $login_url . '?' . http_build_query($params));
}
if (array_key_exists('access_token', $_POST)) {
    $_SESSION['t'] = $_POST['access_token'];
    $t = $_SESSION['t'];
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Authorization: Bearer ' . $t,
        'Content-type: application/json'
    ));
    curl_setopt($ch, CURLOPT_URL, "https://graph.microsoft.com/v1.0/me/");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $rez = json_decode(curl_exec($ch), 1);


    if (array_key_exists('error', $rez)) {
        var_dump($rez);
        die();
    } else {
        $_SESSION['msatg'] = 1;  //auth and verified
        $_SESSION['uname'] = $rez["displayName"];
        $_SESSION['id'] = $rez["id"];
    }
    curl_close($ch);
    header('Location: https://abc.xyz.com/sso/welcome.php');
}

if (isset($_GET['action']) && $_GET['action'] == 'logout') {
    unset($_SESSION['msatg']);
    header('Location: https://abc.xyz.com/sso/');
}

当重定向到welcome.php页面时,我通过var_dump($_SESSION)得到的是空数组,希望会话数据能在该页面正常显示,请问我哪里出错了?


排查与解决办法

1. welcome.php未启动会话

PHP会话需要在每个使用$_SESSION的页面开头调用session_start(),如果welcome.php中缺少这行代码,就无法读取已存储的会话数据。

解决:
在welcome.php的最顶部(任何输出之前)添加:

session_start();

2. 会话Cookie配置不匹配

默认的会话Cookie路径、域名或安全设置可能和你的/sso/目录不兼容,导致重定向后Cookie无法被携带。

解决:
在登录页面的session_start()之前,显式配置会话Cookie参数:

session_set_cookie_params([
    'lifetime' => 0,
    'path' => '/sso/', // 匹配你的SSO目录路径
    'domain' => 'abc.xyz.com', // 不带http/https的域名
    'secure' => true, // HTTPS环境必须开启
    'httponly' => true,
    'samesite' => 'Lax' // 适配POST回调的跨域场景
]);
session_start();

3. 重定向前未强制写入会话数据

调用header('Location: ...')时,会话数据可能还在内存中未写入服务器文件,导致重定向后数据丢失。

解决:
在重定向前添加session_write_close()强制写入,并执行exit终止后续代码:

// 在header()之前添加
session_write_close();
header('Location: https://abc.xyz.com/sso/welcome.php');
exit;

4. 缺失state参数验证(安全+数据一致性问题)

当前代码未验证Azure AD回调返回的state参数是否和之前存储的$_SESSION['state']一致,这不仅存在CSRF风险,也可能因会话不一致导致数据丢失。

解决:
处理POST回调时先验证state:

if (array_key_exists('access_token', $_POST)) {
    // 验证state参数
    if (!isset($_POST['state']) || $_POST['state'] !== $_SESSION['state']) {
        die("Invalid state parameter");
    }
    // 后续业务代码不变
}

5. 服务器会话存储权限问题

如果PHP会话存储目录(默认是/tmp)没有Web服务器用户(如www-data)的读写权限,会话数据无法持久化。

解决:
通过phpinfo()查看session.save_path的值,然后执行权限配置命令:

chown www-data:www-data /path/to/session/dir
chmod 700 /path/to/session/dir

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 13:17:03