Как лучше всего сохранить объект с помощью форм в PHP?

StackOverflow https://stackoverflow.com/questions/617793

  •  03-07-2019
  •  | 
  •  

Вопрос

У меня есть PHP-приложение, в котором я хотел бы, чтобы определенные объекты сохранялись следующим образом:

  1. Объект не должен существовать в $_SESSION.Отдельные окна веб-браузера должны управлять отдельными экземплярами объекта.
  2. Конечный пользователь не должен иметь возможность модифицировать объект, изменяя содержимое переменной $_REQUEST вручную (в этом случае запрос следует рассматривать как поврежденный).

Есть ли передовой опыт/правильный способ сделать это?Поскольку PHP становится все более объектно-ориентированным, я боюсь, что изобретаю велосипед.

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

Мой текущий метод заключается в следующем:

<?php

include('encrypt.php');
include('invoice.class.php');

if(isset($_REQUEST['invoice']))
{
    $invoice = unserialize(decrypt(base64_decode($_REQUEST['invoice'])));
    if(!($invoice instanceOf invoice)) throw new exception('Something bad happened');
}
else
{
    // Some pages throw an exception if the $_REQUEST doesn't exist.
    $invoice = new invoice();
}

if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'addLine')
{
    $invoice->addLine(new invoiceLine($_REQUEST['description'], $_REQUEST['qty'], $_REQUEST['unitprice']);
}

?>
<form action="index.php" method="post">
<input type="text" name="qty" />
...
<input type="hidden" name="invoice" value="<?php echo(base64_encode(encrypt(serialize($invoice)))); ?>" />
</form>
Это было полезно?

Решение

Вы также можете сохранить состояние на клиенте без файлов cookie, используя простой скрытый ввод данных. Пока данные (вероятно, сериализованный большой двоичный объект) зашифрованы и подписаны, пользователь не может изменять их, не прерывая сеанс.

Стив Гибсон использует этот метод для своей системы электронной коммерции. Хотя его код не является открытым исходным кодом, он подробно объясняет способы сохранения состояния без сохранения конфиденциальных данных на сервере и не требует поддержки файлов cookie в Security Now Episode # 109 , " Система электронной коммерции GRC ".

Другие советы

Вот хитрость: поместите это в печенье!

Аккуратный алгоритм:

$ data = serialize ($ object); $ time = time (); $ signature = sha1 ($ serverSideSecret. $ time. $ data); $ cookie = base64 (" $ signature- $ time- $ data ");

Преимущество в том, что вы

a) может истечь срок действия cookie, если вы хотите, потому что вы используете метку времени как часть хэша подписи.

b) может проверить, что данные не были изменены на стороне клиента, потому что вы можете воссоздать хеш из сегмента данных в cookie.

Кроме того, вам не нужно хранить весь объект в файле cookie, если он будет слишком большим. Просто сохраните необходимые данные на сервере и используйте данные в файле cookie в качестве ключа.

Я не могу взять кредит на алгоритм, я узнал это от Кэла Хендерсона, известности Flickr.

Изменить. Если использование файлов cookie слишком сложно, просто забудьте о них и сохраните данные, которые были бы сохранены в файле cookie, в скрытом поле формы.

Я бы сохранил криптографический ключ (а не всю структуру, как в вашем примере) в скрытой переменной формы.Этот ключ является индексом uncreated_invoices таблица, в которой хранятся неполные счета.

Между страницами вы обновляете данные в таблице uncreated_invoices, а когда они будут готовы, извлекаете их и фиксируете.Если вы поместите имя пользователя в таблицу uncreate_invoices, это также позволит им продолжить с того места, где они остановились (не уверен, что это допустимый вариант использования).Вероятно, в любом случае было бы неплохо указать в нем имя пользователя, чтобы люди не могли попытаться украсть счета других людей.

Вероятно, вам удастся сохранить сериализованные данные в таблице uncreated_invoices, если захотите.Лично я бы немного нормализовал его (насколько это зависит от вашей схемы), чтобы вы могли легко добавлять/удалять отдельные части.

Редактировать:Забыл упомянуть, что надо почистить uncreated_invoices таблицу периодически, чтобы она не заполнялась просроченными счетами.

Не удалось сохранить данные в массиве внутри $ _SESSION, а затем иметь уникальный идентификатор для каждого окна. Если каждое окно имеет уникальный идентификатор, вы можете передать его как часть ваших форм. Сохранять / извлекать данные в сеансе или базе данных на основе идентификатора окна.

Так что-то вроде этого? $ _SESSION [ 'данные'] [$ WindowID] - & GT; $ имя_объекта

Если вы не можете использовать SESSION, вы должны сохранить данные самостоятельно. Вы должны поместить данные где-то, где они будут сохраняться, например, в базу данных или какой-либо другой файл. Это единственный способ, кроме СЕССИИ, чтобы сохранить данные.

Я забираю это, вы можете отправлять данные на каждой HTML-странице и использовать их локально. Каждая страница, которая принимает данные, должна создавать HTML / Javascript, который продолжает последовательность данных.

Если вы храните вещи на стороне клиента, они могут быть изменены. Есть ли конкретная причина, по которой вы не хотите хранить объекты в сеансе? Если хранение объекта на самом деле невозможно, вам нужно сохранить его где-то еще на сервере.

Это нормально, они смогут добавлять все элементы, которые они хотят. Проблема в вашем коде состоит в том, что вы берете из запроса дескриптор, количество и ЦЕНУ, цена действительно должна рассматриваться в фоновом режиме, в противном случае, пользователь может вручную обработать их цену. Черт возьми, предметы с отрицательным значением, и вы получаете вещи бесплатно.

Вы хотите что-то сохранить.Обычно это делается в базах данных.Как узнать цену чего-либо, не заглядывая в базу данных?Поэтому используйте ту же базу данных для хранения информации о текущем пользователе/сеансе.

Вы можете использовать магические методы __sleep () и __ wakeup ()

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top