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

PHP使用$_SERVER变量重定向无法返回原请求页问题

问题根因

回跳逻辑失效的核心原因是PHP普通变量无法跨HTTP请求存活:

  • 检测到无活跃会话时,你在当前请求的上下文里给$redirect赋了原访问地址值,紧接着就发送Location头触发浏览器跳转到/confirm_auth.php?sso
  • 这个跳转是让浏览器发起全新的HTTP请求,新请求对应的PHP进程完全感知不到上一个请求里定义的普通变量$redirect,因此isset($redirect)判断永远为false,自然会走到默认跳转首页的分支
  • 代码存在额外隐患:发送header跳转后没有加exit;终止脚本执行,后续逻辑会继续运行,可能引发不可预期的行为
  • 最初贴出的代码里存在拼写错误:跳转域名写为myinternalwebiste.net(website漏写字母b),如果线上代码存在该拼写错误也会直接导致跳转异常,补全的示例代码替换为example.net后不存在该问题。
修复方案

OneLogin SAML工具包本身支持通过RelayState参数自动传递登录后回跳地址,你只需要把原访问地址存储到可跨请求读取的介质中,在触发SAML登录时正确传入回跳地址即可,两种实现方案可任选:

方案1:通过Session暂存回跳地址(最稳妥)

你已经在代码开头调用了session_start(),直接把回跳地址存入$_SESSION数组,跳转到SSO入口页后再从Session读取即可,修改逻辑如下:

  1. 会话校验不通过的else块调整为:
else {
    if (isset($_SERVER['REQUEST_URI'])) {
        // 将回跳地址存入Session,不要使用普通变量存储
        $_SESSION['login_redirect_url'] = "https://example.net" . $_SERVER['REQUEST_URI'];
    }
    header("Location: https://example.net/confirm_auth.php?sso");
    exit; // 必须添加,终止后续代码执行
}
  1. sso参数处理逻辑调整为:
if (isset($_GET['sso'])) {
    // 优先从Session读取之前存储的回跳地址
    if (isset($_SESSION['login_redirect_url'])) {
        $redirect = $_SESSION['login_redirect_url'];
        // 读取后立刻清除该Session字段,避免后续重复触发跳转
        unset($_SESSION['login_redirect_url']);
        $auth->login($redirect);
    } else {
        $auth->login("https://example.net/");
    }
}

方案2:通过URL参数传递回跳地址

如果不想占用Session存储字段,也可以将原地址做URL编码后拼接在跳转链接的查询参数中传递,注意必须做URL编码,否则地址中携带特殊字符时会出现解析错误:

  1. else块跳转逻辑调整为:
else {
    $redirect_query = "";
    if (isset($_SERVER['REQUEST_URI'])) {
        $target_url = "https://example.net" . $_SERVER['REQUEST_URI'];
        $redirect_query = "&redirect=" . urlencode($target_url);
    }
    header("Location: https://example.net/confirm_auth.php?sso" . $redirect_query);
    exit;
}
  1. sso参数处理逻辑对应从$_GET中读取回跳地址,注意必须做域名合法性校验,避免造成开放重定向漏洞:
if (isset($_GET['sso'])) {
    if (isset($_GET['redirect'])) {
        $redirect = $_GET['redirect'];
        // 仅允许跳转到本站点域名,防止被利用跳转至恶意站点
        if (parse_url($redirect, PHP_URL_HOST) === "example.net") {
            $auth->login($redirect);
        } else {
            $auth->login("https://example.net/");
        }
    } else {
        $auth->login("https://example.net/");
    }
}
补充说明

你在ACS回调逻辑中已经编写了RelayState的跳转处理,只要调用$auth->login()时传入的回跳地址正确,SAML工具包会自动将该地址写入RelayState参数,完成IdP认证回调后即可自动跳回用户最初访问的页面,不需要额外编写跳转逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 00:31:08