简体   繁体   English

带有 Post 参数的 PHP 重定向

[英]PHP Redirection with Post Parameters

I have a webpage.我有一个网页。 This webpage redirects the user to another webpage, more or less the following way:该网页或多或少通过以下方式将用户重定向到另一个网页:

<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>

Well, you see, what I do is transferring the GET params into POST params.好吧,你看,我所做的是将 GET 参数转换为 POST 参数。 Do not tell me it is bad, I know that myself, and it is not exactly what I really do, what is important is that I collect data from an array and try submitting it to another page via POST.不要告诉我它不好,我自己知道,这并不是我真正做的事情,重要的是我从数组中收集数据并尝试通过 POST 将其提交到另一个页面。 But if the user has JavaScript turned off, it won't work.但是如果用户关闭了 JavaScript,它将无法工作。 What I need to know: Is there a way to transfer POST parameters by means of PHP so the redirection can be done the PHP way ( header('Location: anotherpage.php'); ), too?我需要知道的是:有没有办法通过 PHP 传输 POST 参数,以便可以通过 PHP 方式( header('Location: anotherpage.php'); )完成重定向?

It is very important for me to pass the params via POST.通过 POST 传递参数对我来说非常重要。 I cannot use the $_SESSION variable because the webpage is on another domain, thus, the $_SESSION variables differ.我无法使用 $_SESSION 变量,因为该网页位于另一个域中,因此 $_SESSION 变量不同。

Anyway, I simply need a way to transfer POST variables with PHP ^^无论如何,我只需要一种使用 PHP 传输 POST 变量的方法 ^^

Thanks in advance!提前致谢!

You CAN header redirect a POST request, and include the POST information.您可以通过标头重定向 POST 请求,并包含 POST 信息。 However, you need to explicitly return HTTP status code 307. Browsers treat 302 as a redirect with for GET, ignoring the original method.但是,您需要显式返回 HTTP 状态代码 307。浏览器将 302 视为使用 GET 重定向,忽略原始方法。 This is noted explicitly in the HTTP documentation:这在 HTTP 文档中明确指出:

Practically, this means in PHP you need to set the status code before the redirect location:实际上,这意味着在 PHP 中您需要在重定向位置之前设置状态代码:

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

However, note that according to the HTTP specification, the user agent MUST ask user if they are ok resubmitting the POST information to the new URL.但是,请注意,根据 HTTP 规范,用户代理必须询问用户是否可以将 POST 信息重新提交到新 URL。 In practical terms, Chrome doesn't ask, and neither does Safari, but Firefox will present the user with a popup box confirming the redirection.实际上,Chrome 不会询问,Safari 也不会询问,但 Firefox 会向用户显示一个确认重定向的弹出框。 Depending on your operating constraints, maybe this is ok, although in a general usage case it certainly has the potential to cause confusion for end users.根据您的操作限制,这可能没问题,但在一般使用情况下,它肯定有可能给最终用户造成混淆。

No possibility to do this directly from server, as POST data should be sent by the browser.无法直接从服务器执行此操作,因为 POST 数据应由浏览器发送。

But you can choose an alternative:但是你可以选择一个替代方案:

  • The prefilled form automatically submitted in your example could work, but as you wrote it's not really good practice and can leave users on a blank page在您的示例中自动提交的预填表单可以工作,但正如您所写的那样,这不是一个很好的做法,可能会让用户停留在空白页面上
  • Receive GET arguments and POST them with curl (or any decent HTTP client) to the second site, then transfer the result to the browser.接收 GET 参数并使用 curl(或任何像样的 HTTP 客户端)将它们 POST 到第二个站点,然后将结果传输到浏览器。 This is called a proxy and may be a good solution IMHO.这称为代理,恕我直言,这可能是一个很好的解决方案。
  • Do session sharing across domain, this can not be possible on all setups and can be complex.跨域进行会话共享,这在所有设置中都是不可能的,并且可能很复杂。 Once setup is done, session sharing is almost transparent to PHP code.设置完成后,会话共享对 PHP 代码几乎是透明的。 If you have more than one need for communication between the 2 domains it can be worth doing this.如果您对 2 个域之间的通信有不止一种需求,那么这样做是值得的。

Example with curl solution, code to run on domain 1: 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;

That's it, your client's browser won't even see domain 2 server, it will get only result from it.就是这样,您客户端的浏览器甚至不会看到域 2 服务器,它只会从中获得结果。 know if you want to redirect client to domain, do it with classic HTTP header.知道是否要将客户端重定向到域,请使用经典的 HTTP 标头进行。

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

Of course, this is demo code with hardcoded values, and there are 2 point left to you:当然,这是带有硬编码值的演示代码,还有两点留给您:

  • Security: query string should be filtered or recreated to transmit only needed parameters, and you should assert the server on domain 2 returned a 200 HTTP code.安全性:应该过滤或重新创建查询字符串以仅传输需要的参数,并且您应该断言域 2 上的服务器返回 200 HTTP 代码。
  • Application logic should need a little adjustment on this part: if domain 2 app expects to get post data in the same request as visitor is coming it won't do it.应用程序逻辑在这部分应该需要一些调整:如果域 2 应用程序希望在访问者到来的同一请求中获取发布数据,它不会这样做。 From domain 2 point of view, the client doing POST request will be server hosting domain 1 not the client browser, it's important if client IP matters or other client checks are done on domain 2. If the POST request serves to display client specific content you also had to do some server-side tracking to combine previously posted data with the visitor being redirected.从域 2 的角度来看,执行 POST 请求的客户端将是托管域 1 的服务器而不是客户端浏览器,如果客户端 IP 问题或其他客户端检查在域 2 上完成,这一点很重要。如果 POST 请求用于显示客户端特定的内容,您还必须进行一些服务器端跟踪,以将先前发布的数据与被重定向的访问者结合起来。

You could hack something together like the following... (I'm not saying you should however!):可以像下面这样一起破解一些东西......(我并不是说你应该这样做!):

$res = "<form action='/path/to/new/page' method='POST' id='redirectHack'>
            <input type='hidden' id='postVar1' name='postVar1' value='12345'>
            <input type='hidden' id='postVar2' name='postVar2' value='67890'>
        </form>
        <script>
            document.getElementById('redirectHack').submit()
        </script>";
die($res);

This can be done using php cUrl lib.这可以使用 php cUrl lib 来完成。

Check this http://www.askapache.com/htaccess/sending-post-form-data-with-php-curl.html检查这个http://www.askapache.com/htaccess/sending-post-form-data-with-php-curl.html

Thanks, Sourabh谢谢,苏拉布

将您的数据存储在会话中,然后使用 GET。

No. You can't do header redirect with POST.不。您不能使用 POST 进行标头重定向。 You have 2 options,你有2个选择,

  1. You can use GET instead if the destination accepts either POST or GET.如果目标接受 POST 或 GET,您可以改用 GET。
  2. We add a button in rare cases that the Javascript is turned off.我们会在 Javascript 关闭的极少数情况下添加一个按钮。

Here is an example,这是一个例子,

<noscript>
<div>
<input type="submit" value="Continue"/>
</div>
</noscript>

This will show a continue button if Javascript is off so user can click to continue.如果 Javascript 关闭,这将显示一个继续按钮,以便用户可以单击继续。

It is possible.有可能的。 In this situation I would use cURL:在这种情况下,我会使用 cURL:

$url = 'http://domain.com/get-post.php';


foreach($_GET as $key=>$value) { 
  $fields_string .= $key.'='.$value.'&'; 
}
rtrim($fields_string,'&');

//open connection
$ch = curl_init();

//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);

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

//close connection
curl_close($ch);

As a sample of what @Charles indicates, here is a working php PayPal buy form that:作为@Charles 表示的示例,这是一个有效的 php PayPal 购买表单:

  1. Checks the input with javascript.使用 javascript 检查输入。 If OK, it submits it, else displays an alert.如果正常,则提交它,否则显示警报。
  2. Checks the input with php.使用 php 检查输入。 If OK, it creates the redirect headers and gets rid of the body HTML, else it shows the same form again.如果正常,它会创建重定向标头并删除正文 HTML,否则它会再次显示相同的表单。

Note that:注意:

  1. Inputs should be rechecked on the server, as a browser's inputs can be nefariously manipulated.应该在服务器上重新检查输入,因为浏览器的输入可以被恶意操纵。
  2. No HTML can be output before the header commands, as they will be ignored with a php warning.在标头命令之前不能输出 HTML,因为它们会被 php 警告忽略。
  3. Javascript can only check the inputs for valid values, but without AJAX, will not be able to check the server for whatever the user wants before submission. Javascript 只能检查输入的有效值,但没有 AJAX,将无法在提交之前检查服务器是否有用户想要的任何内容。 Therefore, this method is the complete non-javascript process.因此,此方法是完整的非javascript 过程。
  4. No HTML is needed if the redirect target (like PayPal) is only processing the POST data.如果重定向目标(如 PayPal)仅处理 POST 数据,则不需要 HTML。 Targets for humans do, of course!人类的目标当然可以!
  5. Unfortunately, 4 means that you cannot send just a subset or even a complete other set of values to the new url, AND have the target page processing the POST data open in the user 's browser.不幸的是,4 意味着您不能只向新 url 发送一个子集甚至一组完整的其他值,并且让目标页面处理 POST 数据在用户的浏览器中打开。 You cannot do this by manipulating the $_POST array (it seems to be just a PHP copy of the actual data).您不能通过操作 $_POST 数组来做到这一点(它似乎只是实际数据的 PHP 副本)。 Perhaps someone knows how to modify the real POST data set?也许有人知道如何修改真实的POST数据集?
  6. From 5, there is no opportunity to gather private information on the original form, and just send only the payment information on the form to PayPal or whomever, via the user's browser for their explicit payment approval.从 5 开始,没有机会收集原始表单上的私人信息,只需将表单上的付款信息发送给 PayPal 或任何人,通过用户的浏览器进行明确的付款批准。 That means AJAX is needed to do that by using two forms, one holding the private info with no button, and the other form with the PayPal buy button that uses AJAX to submit the other form, and depending upon the result, submit its own form.这意味着 AJAX 需要通过使用两种形式来做到这一点,一种包含没有按钮的私人信息,另一种带有 PayPal 购买按钮的表单使用 AJAX 提交另一个表单,并根据结果提交自己的表单. You could use fields that PayPal doesn't use, but they are still getting the info, and we don't know what they have trawling over submitted form data.您可以使用 PayPal 不使用的字段,但他们仍在获取信息,而且我们不知道他们对提交的表单数据进行了哪些搜索。
  7. Rather than using AJAX as in 6, it would be a lot simpler to have 3 versions of the form:与在 6 中使用 AJAX 不同,拥有 3 个版本的表单会简单得多:
    1. Initial to capture the private data.初始捕获私有数据。
    2. If problem, re-show form with submitted data and indication of incorrect data or backend problem.如果出现问题,请重新显示包含已提交数据的表单并指出不正确的数据或后端问题。
    3. If OK, a PayPal form, submitted automatically by javascript at the bottom of the page (form.submit()), or a request to submit manually by a button if no javascript.如果正常,一个 PayPal 表单,由页面底部的 javascript 自动提交 (form.submit()),或者如果没有 javascript,则请求通过按钮手动提交。

 <?php // GET POST VARIABLES, ELSE SET DEFAULTS $sAction=(isset($_POST['action'])?$_POST['action']:''); $nAmount=(int)(isset($_POST['action'])?$_POST['amount']:0); // TEST IF AMOUNT OK $bOK=($nAmount>=10); /* TYPICAL CHECKS: 1. Fields have valid values, as a backup to the javascript. 2. Backend can fulfil the request. Such as whether the requested stock item or appointment is still available, and reserve it for 10-15 minutes while the payment goes through. If all OK, you want the new URL page, such as PayPal to open immediately. */ // IF OK if($bOK){ // CHANGE HEADER TO NEW URL $sURL='https://www.paypal.com/cgi-bin/webscr'; header('HTTP/1.1 307 Temporary Redirect'); header('Location: '.$sURL); } ?> <!DOCTYPE html> <html> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> <title>Sample post redirection</title> </head> <body> <?php // IF NO ACTION OR NOT OK if(($sAction=='')||!$bOK){ ?> <h1>Sample post redirection</h1> <p>Throw money at me:</p> <form name="pp" action="<?=$_SERVER['REQUEST_URI']?>" method="post" onsubmit="check_form(this)"> <!-- <input type="hidden" name="amount" value="<?=$nAmount?>" /> --> <input type="hidden" name="business" value="paypal.email@yourdomain.com" /> <input type="hidden" name="cmd" value="_xclick" /> <input type="hidden" name="lc" value="AU" /> <input type="hidden" name="item_name" value="Name of service" /> <input type="hidden" name="item_number" value="service_id" /> <input type="hidden" name="currency_code" value="AUD" /> <input type="hidden" name="button_subtype" value="services" /> <input type="hidden" name="no_note" value="0" /> <input type="hidden" name="shipping" value="0.00" /> <input type="hidden" name="on0" value="Private" /> <input type="hidden" name="os0" value="Xxxx xxxxx xxxxx" /> <p>Amount $<input id="amount" type="text" name="amount" value="<?=$nAmount?>" /> $10 or more.</p> <p><button type="submit" name="action" value="buy">Buy</button></p> </form> <p>If all is OK, you will be redirected to the PayPal payment page.<br /> If your browser requires confirmation, click the <cite>OK</cite> button.</p> <script> // JS AT END OF PAGE TO PREVENT HTML RENDER BLOCKING // JS FUNCTION FOR LOCAL CHECKING OF FIELD VALUES function check_form(oForm){ // USE TO DETERMINE IF VALUES CORRECT var oAmount=document.getElementById('amount'); var nAmount=oAmount.value; var bOK=true; var bOK=(nAmount>=10); // EXAMINE VALUES // IF NOT OK if(!bOK){ // INDICATE WHAT'S WRONG, ALERT ETC alert('Stingy @$#&. Pay more!!'); // BLOCK FORM SUBMIT ON ALL BROWSERS event.preventDefault(); event.stopPropagation(); return false; } } </script> <?php } ?> </body> </html>

In a POST Redirect GET situation, ( see https://en.wikipedia.org/wiki/Post/Redirect/Get ) it is acceptable to use the session variable as the method of transporting the data.在 POST 重定向 GET 情况下,(请参阅https://en.wikipedia.org/wiki/Post/Redirect/Get )使用会话变量作为传输数据的方法是可以接受的。

<?php
session_start();

// return is the name of a checkbox in the post-redirect-get.php script. 
if(isset($_POST['return'])) {
    // We add some data based on some sort of computation and
    // return it to the calling script
    $_SESSION['action']="This string represents data in this example!";
    header('location: post-redirect-get.php');
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM