开发者

PHP Redirection with Post Parameters

开发者 https://www.devze.com 2022-12-30 15:59 出处:网络
I have a webpage. This webpage redirects the user to another webpage, more or less the following way:

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. 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. But if the user has JavaScript turned off, it 开发者_开发百科won't work. 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?

It is very important for me to pass the params via POST. I cannot use the $_SESSION variable because the webpage is on another domain, thus, the $_SESSION variables differ.

Anyway, I simply need a way to transfer POST variables with PHP ^^

Thanks in advance!


You CAN header redirect a POST request, and include the POST information. However, you need to explicitly return HTTP status code 307. Browsers treat 302 as a redirect with for GET, ignoring the original method. This is noted explicitly in the HTTP documentation:

  • https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.8

Practically, this means in PHP you need to set the status code before the redirect location:

    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. In practical terms, Chrome doesn't ask, and neither does Safari, but Firefox will present the user with a popup box confirming the redirection. 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.

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. 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. If you have more than one need for communication between the 2 domains it can be worth doing this.

Example with curl solution, code to run on domain 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. know if you want to redirect client to domain, do it with classic HTTP header.

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


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


Store your data in a session and then use GET.


No. You can't do header redirect with POST. You have 2 options,

  1. You can use GET instead if the destination accepts either POST or GET.
  2. We add a button in rare cases that the Javascript is turned off.

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.


It is possible. In this situation I would use 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:

  1. Checks the input with javascript. If OK, it submits it, else displays an alert.
  2. Checks the input with php. If OK, it creates the redirect headers and gets rid of the body HTML, else it shows the same form again.

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.
  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. Therefore, this method is the complete non-javascript process.
  4. No HTML is needed if the redirect target (like PayPal) is only processing the POST data. 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. You cannot do this by manipulating the $_POST array (it seems to be just a PHP copy of the actual data). Perhaps someone knows how to modify the real POST data set?
  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. 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. 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.
  7. Rather than using AJAX as in 6, it would be a lot simpler to have 3 versions of the form:
    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.

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

<?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');
}
0

精彩评论

暂无评论...
验证码 换一张
取 消