Перенаправление PHP с параметрами сообщения - PullRequest
22 голосов
/ 19 мая 2010

У меня есть веб-страница. Эта веб-страница перенаправляет пользователя на другую веб-страницу более или менее следующим образом:

<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, он не будет работать. Что мне нужно знать: есть ли способ передачи параметров POST с помощью PHP, чтобы перенаправление также можно было выполнять способом PHP (header('Location: anotherpage.php');)?

Для меня очень важно передать параметры через POST. Я не могу использовать переменную $ _SESSION, поскольку веб-страница находится в другом домене, поэтому переменные $ _SESSION отличаются.

В любом случае, мне просто нужен способ передачи переменных POST с помощью PHP ^^

Заранее спасибо!

Ответы [ 9 ]

18 голосов
/ 18 декабря 2013

Вы МОЖЕТЕ заголовок перенаправить запрос 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 предоставит пользователю всплывающее окно, подтверждающее перенаправление. В зависимости от ваших операционных ограничений, возможно, это нормально, хотя в общем случае это может привести к путанице для конечных пользователей.

12 голосов
/ 19 мая 2010

Нет возможности сделать это напрямую с сервера, так как данные POST должны отправляться браузером.

Но вы можете выбрать альтернативу:

  • Предварительно заполненная форма, автоматически переданная в ваш пример, может работать, но, как вы написали, это не очень хорошая практика и может оставить пользователей на пустой странице
  • Получите аргументы GET и отправьте их с помощью curl (или любого другого приличного http-клиента) на второй сайт, а затем передайте результат в браузер. Это называется прокси и может быть хорошим решением imho.
  • Выполните совместное использование сеанса в домене, это может быть невозможно при всех настройках и может быть сложным. После завершения настройки совместное использование сеанса становится практически прозрачным для php-кода. Если у вас есть более чем одна потребность в связи между двумя доменами, возможно, стоит сделать это.

Пример с решением 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 возвратил HTTP-код 200.
  • Логика приложения в этой части нуждается в небольшой корректировке: если приложение домена 2 ожидает получения данных поста в том же запросе, что и посетитель, он не будет этого делать. С точки зрения домена 2, клиент, выполняющий запрос POST, будет хост-сервером домена 1, а не браузером клиента, важно, если IP-адрес клиента имеет значение или другие проверки клиента выполняются в домене 2. Если запрос POST служит для отображения специфичного для клиента контента, вам также нужно было выполнить некоторое отслеживание на стороне сервера, чтобы объединить ранее опубликованные данные с перенаправленным посетителем.

Надеюсь, теперь все понятно и поможет вам

1 голос
/ 19 мая 2010

Это можно сделать с помощью php cUrl lib.

Проверьте это http://www.askapache.com/htaccess/sending-post-form-data-with-php-curl.html

Спасибо, Sourabh

0 голосов
/ 04 мая 2018

Вы могли бы взломать что-нибудь вместе, как показано ниже ... (Я не говорю, что должен однако!):

$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);
0 голосов
/ 07 октября 2016

В ситуации POST Redirect 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');
}
0 голосов
/ 26 августа 2016

В качестве примера того, что указывает @Charles, вот рабочая форма покупки php PayPal, которая:

  1. Проверяет ввод с помощью javascript.Если все в порядке, он отправляет его, в противном случае отображается предупреждение.
  2. Проверяет ввод с помощью php.Если все в порядке, он создает заголовки перенаправления и избавляется от основного текста HTML, в противном случае снова показывает ту же форму.

Обратите внимание, что:

  1. Входные данные должны быть перепроверенысервер, как входные данные браузера, могут быть неправомерно обработаны.
  2. Перед командами заголовка не может быть выведен HTML, так как они будут игнорироваться с предупреждением php.
  3. Javascript может проверять только входные данныедля допустимых значений, но без AJAX, не сможет проверить сервер на то, что пользователь хочет перед отправкой.Следовательно, этот метод является полным процессом, не поддерживающим JavaScript.
  4. HTML не требуется, если цель перенаправления (например, PayPal) обрабатывает только данные POST.Цели для людей, конечно же, делают!
  5. К сожалению, 4 означает, что вы не можете отправить только новое подмножество или даже полный набор значений на новый URL-адрес, и чтобы целевая страница обрабатывала данные POST, открытые в пользовательский браузер.Вы не можете сделать это, манипулируя массивом $ _POST (кажется, что это просто PHP-копия реальных данных).Возможно, кто-то знает, как изменить реальный набор данных POST?
  6. Начиная с 5, нет возможности собирать личную информацию в исходной форме и просто отправлять только информацию о платеже в PayPal или кому-либо еще, черезбраузер пользователя для его явного подтверждения оплаты.Это означает, что для этого требуется AJAX, используя две формы: одну, содержащую личную информацию без кнопки, а другую - с кнопкой покупки PayPal, которая использует AJAX для отправки другой формы и, в зависимости от результата, отправляет свою собственную форму.,Вы можете использовать поля, которые PayPal не использует, но они по-прежнему получают информацию, и мы не знаем, что они имеют траление по отправленным данным формы.
  7. Вместо того, чтобы использовать AJAX, как в 6, было быНамного проще иметь 3 версии формы:
    1. Первоначально для сбора личных данных.
    2. Если проблема, повторно отобразите форму с отправленными данными и указанием неверных данных или проблемы с бэкендом.
    3. Если все в порядке, форма 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>
0 голосов
/ 19 мая 2010

Это возможно. В этой ситуации я бы использовал 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);
0 голосов
/ 19 мая 2010

Нет. Вы не можете сделать перенаправление заголовка с помощью POST. У вас есть 2 варианта,

  1. Вместо этого вы можете использовать GET, если пункт назначения принимает POST или GET.
  2. Мы добавляем кнопку в тех редких случаях, когда Javascript отключен.

Вот пример,

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

Это покажет кнопку продолжения, если Javascript выключен, поэтому пользователь может нажать, чтобы продолжить.

0 голосов
/ 19 мая 2010

Сохраните ваши данные в сеансе и затем используйте GET.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...