带有 Post 参数的 PHP 重定向

2022-08-30 15:39:06

我有一个网页。此网页将用户重定向到另一个网页,或多或少通过以下方式:

<form method="post" action="anotherpage.php" id="myform">

    <?php foreach($_GET as $key => $value){
    echo "<input type='hidden' name='{$key}' value='{$value}' />";
    } ?>

</form>
<script>

    document.getElementById('myform').submit();

</script>

好吧,你看,我所做的是将GET参数转移到POST参数中。不要告诉我这是不好的,我自己也知道,这并不是我真正要做的,重要的是我从数组中收集数据并尝试通过POST将其提交到另一个页面。但是,如果用户关闭了JavaScript,它将不起作用。我需要知道的是:有没有办法通过PHP传输POST参数,以便重定向也可以以PHP方式()完成?header('Location: anotherpage.php');

对我来说,通过POST传递参数非常重要。我不能使用 $_SESSION 变量,因为网页位于另一个域上,因此 $_SESSION 变量不同。

无论如何,我只需要一种方法来转移PHP变量^^

提前致谢!


答案 1

您可以标头重定向 POST 请求,并包含 POST 信息。但是,您需要显式返回 HTTP 状态代码 307。浏览器将 302 视为 GET 的重定向,忽略原始方法。这在 HTTP 文档中明确指出:

实际上,这意味着在PHP中,您需要在重定向位置之前设置状态代码:

    header('HTTP/1.1 307 Temporary Redirect');
    header('Location: anotherpage.php');

但是,请注意,根据 HTTP 规范,用户代理必须询问用户是否可以将 POST 信息重新提交到新 URL。实际上,Chrome不会询问,Safari也不会,但Firefox会向用户显示一个确认重定向的弹出框。根据您的操作限制,也许这是可以的,尽管在一般用例中,它肯定有可能给最终用户带来混乱。


答案 2

不可能直接从服务器执行此操作,因为POST数据应由浏览器发送。

但您可以选择替代方案:

  • 在您的示例中自动提交的预填表单可以工作,但正如您所写的那样,这并不是很好的做法,并且可能会使用户处于空白页面
  • 接收GET参数并使用curl(或任何像样的HTTP客户端)将它们发布到第二个站点,然后将结果传输到浏览器。这被称为代理,恕我直言,这可能是一个很好的解决方案。
  • 跨域进行会话共享,这不可能在所有设置上都实现,并且可能很复杂。设置完成后,会话共享对 PHP 代码几乎是透明的。如果您在2个域之间有多个通信需求,则值得这样做。

curl 解决方案示例,要在域 1 上运行的代码:

//retrieve GET parameters as a string like arg1=0&arg1=56&argn=zz
$data = $_SERVER['QUERY_STRING']; 

// Create a curl handle to domain 2
$ch = curl_init('http://www.domain2.com/target_script.php'); 

//configure a POST request with some options
curl_setopt($ch, CURLOPT_POST, true);
//put data to send
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);    
//this option avoid retrieving HTTP response headers in answer
curl_setopt($ch, CURLOPT_HEADER, 0);
//we want to get result as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//if servers support is and you want result faster, allow compressed response
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate'); 

//execute request
$result = curl_exec($ch);

//show response form domain 2 to client if needed
echo $result;

就是这样,您客户端的浏览器甚至不会看到域2服务器,它只会从中获得结果。知道如果你想将客户端重定向到域,请使用经典的HTTP标头。

header('Location: http://www.domain2.com');

当然,这是具有硬编码值的演示代码,还有2点留给您:

  • 安全性:应筛选或重新创建查询字符串以仅传输所需的参数,并且应断言域 2 上的服务器返回了 200 HTTP 代码。
  • 应用程序逻辑应该需要对这部分进行一些调整:如果域2应用程序希望在与访问者来访者相同的请求中获取帖子数据,则不会这样做。从域 2 的角度来看,执行 POST 请求的客户端将是服务器托管域 1 而不是客户端浏览器,如果客户端 IP 很重要或在域 2 上执行其他客户端检查,这一点很重要。如果 POST 请求用于显示客户端特定的内容,则还必须执行一些服务器端跟踪,以将以前发布的数据与被重定向的访问者相结合。