Разработчику. Сборник рецептов PHP
Задавайте вопросы

Работа с многостраничными формами

Вернуться назад

Задача

Необходимо использовать форму, которая показывает более одной страницы и сохраняет данные при переходе от одной страницы к следующей.

Решение

Используйте сеансы:

session_start();
$_SESSION['username'] = $_GET['username'];

Можно также включать переменные из формы более ранней страницы в качестве скрытых полей ввода в более поздних страницах:

<input type="hidden" name="username"
     value="<?php echo htmlentities($_GET['username']); ?>">

Обсуждение

При любой возможности используйте сеансы. Это более безопасно, поскольку пользователь не может модифицировать переменные сеанса. Чтобы начать сеанс, вызовите функцию session_start(), которая создаст новый сеанс или продолжит существующий. Заметим, что этот этап не является необходимым, если в файле php.ini установлен параметр session.auto_start. Переменные, присвоенные массиву $_SESSION, автоматически передаются между сценариями. В примере, показанном в разделе «Решение», переменная формы username сохраняется с помощью присваивания элемента $_GET['username'] элементу $_SESSION['username'].

Для получения доступа к этому значению в последующем запросе вызовите функцию session_start(), а затем проверьте элемент $_SESSION['username']:

session_start();
$username = htmlentities($_SESSION['username']);
print "Hello $username.";

В данном случае, если не вызвать функцию session_start(), то массив $_SESSION не будет установлен. Обеспечьте безопасность сервера и сохраните в секрете место расположения файлов сеанса (системных файлов, базы данных и т. д.); в противном случае ваша система будет уязвима для соединений с ложной аутентификацией.

Если использование сеансов не разрешено для вашей инсталляции PHP, то взамен можно использовать скрытые переменные формы. Однако передача данных с помощью скрытых элементов формы небезопасна, поскольку кто-нибудь может отредактировать эти поля и подделать запрос; но, приложив небольшие усилия, можно повысить безопасность до приемлемого уровня.

Основной способ применения скрытых полей состоит в том, чтобы включить их внутрь формы.

<form action="<?php echo $_SERVER['PHP_SELF']; ?>"
     method="get">

<input type="hidden" name="username"
     value="<?php echo htmlentities($_GET['username']); ?>">

После того как эта форма будет отправлена повторно, элемент $_GET['username'] будет содержать предыдущее значение, если только кто-нибудь не поменяет его.

Есть и более сложное, но безопасное решение – преобразовать переменные в строку с помощью функции serialize(), вычислить секретный хеш из данных и поместить обе части информации в форму. Затем в следующем запросе проверьте достоверность данных и выполните обратное преобразование. Если данные не пройдут проверки на достоверность, вы будете знать, что кто-то пытался модифицировать информацию.

Кодирующая функция pc_encode(), показанная в примере pc_encode(), принимает данные для декодирования в виде массива.

Пример: pc_encode()

$secret = 'Foo25bAr52baZ';

function pc_encode($data) {
     $data = serialize($data);
     $hash = md5($GLOBALS['secret'] . $data);
     return array($data, $hash);

}

В функции c_encode() данные преобразуются в строку, вычисляется контрольный хеш и эти переменные возвращаются.

Функция pc_decode(), показанная в примере: pc_decode(), делает работу обратную той, которую выполнил ее двойник.

Пример pc_decode()

function pc_decode($data, $hash) {
     if (!empty($data) && !empty($hash)) {
          if (md5($GLOBALS['secret'] . $data) == $hash) {
               return unserialize($data);
          } else {
               error_log("Validation Error: Data has been modified");
               return false;
          }
     }
     eturn false;
}

Функция pc_decode() вновь создает хеш секретного слова с данными и сравнивает его со значением хеша из формы. Если они равны, то переменная $data считается достоверной и поэтому над ней выполняется обратное преобразование. Если проверка заканчивается неудачей, то функция записывает сообщение в журнал ошибок и возвращает false.

Эти функции работают вместе следующим образом:

<?php
$secret = 'Foo25bAr52baZ';

// Загружаем старые данные и проверяем их достоверность
if (! $data = pc_decode($_GET['data'], $_GET['hash'])) {
// попытка взлома

}
// Обрабатываем форму (новые данные формы находятся в $_GET)

// Обновляем $data
$data['username'] = $_GET['username'];
$data['stage']++;
unset($data['password']);

// Кодируем результаты
list ($data, $hash) = pc_encode($data);

// Сохраняем данные и хеш внутри формы
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get">

...

<input type="hidden" name="data"
     value="<?php echo htmlentities($data); ?>">
<input type="hidden" name="hash"
     value="<?php echo htmlentities($hash); ?>">
</form>

В начале сценария мы передаем функции pc_decode() переменные из формы для декодирования. Как только информация загружена в массив $data, обработку формы можно продолжить, проверяя новые переменные в массиве $_GET, а старые переменные в $data. После завершения проверки обновляем массив $data, сохраняя в нем новые переменные, вычисляя по пути хеш. Наконец, выводим новую форму и включаем $data и $hash как скрытые переменные.

См. также

Документацию по функции serialize() на http://www.php.net/serialize и по функции unserialize() на http://www.php.net/unserialize.

Вернуться назад

Рейтинг@Mail.ru

Яндекс.Метрика

Индекс цитирования


Рейтинг Сайтов ДОСКИ.РУ