Pergunta

Eu tenho uma aplicação PHP onde eu gostaria de certos objetos de persistir, da seguinte maneira:

  1. O objeto não deve existir no $ _SESSION. janelas do navegador web separadas deve controlar instâncias separadas do objeto.
  2. O usuário final não deve ser capaz de modificar o objeto alterando o conteúdo da variável _REQUEST $ à mão (se isso acontece, o pedido deve ser tratado como corrompido).

Existe uma melhores práticas / maneira correta de fazer isso? Com PHP cada vez mais orientada a objetos, temo que eu estou reinventando a roda.

O grande propósito deste código é permitir a criação e manipulação de objetos complexos sem o uso de um banco de dados até que estejam a ser cometidos, então eu vou usar uma transação adequada para cometê-los ao banco de dados na íntegra. Eu quero fazer com que meu banco de dados contém apenas a fatura completa, ou nenhuma factura em tudo.

Meu método atual é a seguinte:

<?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>
Foi útil?

Solução

Você também pode salvar o estado no cliente, sem cookies, usando um simples escondida entrada de formulário. Enquanto os dados (provavelmente um blob serializado) é criptografado e assinado, o usuário não pode modificá-lo sem quebrar a sua sessão.

Steve Gibson usa este método para seu costume sistema de e-commerce. Enquanto seu código não é open source, ele absolutamente explica maneiras de economizar estado sem armazenar dados sensíveis no servidor ou que requerem suporte de cookie no Segurança Agora Episódio # 109 , "sistema de comércio eletrônico do GRC".

Outras dicas

Aqui está um truque: colocá-lo em um cookie

algoritmo puro:

$ dados = serialize ($ object); $ Tempo = tempo (); $ Signature = sha1 ($ serverSideSecret $ time $ data..); $ Bolinho = base64 ( "$ signature- $ tempo- $ dados");

A vantagem é que você

a) pode expirar o cookie quando você quer porque você está usando o timestamp como parte do hash de assinatura.

b) pode verificar que os dados não foi modificado no lado do cliente, porque você pode recriar o hash do segmento de dados no cookie.

Além disso, você não tem que armazenar o objeto inteiro no cookie se ele vai ser muito grande. Apenas armazenar os dados que você precisa no servidor e usar os dados no cookie como uma chave.

Eu não posso levar o crédito para o algoritmo, aprendi-o de Cal Henderson, do Flickr fama.

Edit:. Se você encontrar usando cookies muito complicado, simplesmente esquecê-los e armazenar os dados que teriam ido no cookie em um campo de formulário oculto

O que eu gostaria de fazer é armazenar um tecla (não toda a estrutura, como o seu exemplo é) criptográfico em uma variável de forma oculta. Esta chave é um índice para uma tabela uncreated_invoices onde armazenar as facturas incompletas.

Entre páginas, você atualizar os dados na tabela de uncreated_invoices, e quando estiver pronto, retire-o e cometê-lo. Se você colocar o nome de usuário na tabela de uncreate_invoices, isso também vai deixá-los pegar onde parou (não tenho certeza se isso é um caso de uso válido). Provavelmente seria uma boa idéia de colocar o nome de usuário nele de qualquer maneira para que as pessoas não podem tentar seqüestrar faturas de outras pessoas.

Você pode provavelmente começar afastado com o armazenamento de dados serializados na tabela de uncreated_invoices, se você quisesse. Pessoalmente, eu normalizá-lo um pouco (o quanto depende do seu esquema) para que você pode facilmente adicionar / remover peças individuais.

Edit: Eu esqueci de mencionar que você deve limpar a mesa de uncreated_invoices periodicamente para que ele não encher-se de faturas obsoletos.

Não foi possível armazenar os dados em uma matriz dentro de $ _SESSION, e então ter um ID único para cada janela. Se cada janela tem id único você pode passar a ID ao redor como parte de suas formas. Loja / recuperar os dados da sessão ou banco de dados baseado no id janela.

Então, alguma coisa assim? $ _SESSION [ 'data'] [$ WindowID] -> $ objectname

Se você não pode usar SESSION então você deve manter os dados mesmo. Você deve colocar o em algum lugar dados que persistirá, como um banco de dados ou algum outro arquivo. É a única maneira, além sessão para Persit dados.

Eu levo isso de volta, você pode enviar os dados em cada página HTML e usá-lo localmente. Cada página que aceita os dados devem criar HTML / Javascript que continua a sequência de dados.

Se você armazenar coisas no cliente lado eles podem ser modificados. Existe uma razão específica que você não deseja armazenar os objetos em uma sessão? Se a armazenar o objeto realmente não é viável que você precisa para persistir em outro lugar no servidor.

Isso é bom, eles vão ser capazes de adicionar todos os itens que eles querem. O problema no seu código é que você está tomando o descritor item, quantidade e preço do pedido, o preço realmente deve ser procurado em segundo plano, caso contrário, um usuário poderia entregar ofício seu preço. Heck, itens de valor negativas, e você receber coisas de graça.

Você deseja armazenar alguma coisa. Isso é geralmente feito em bancos de dados. Como você sabe o preço de algo sem olhar-lo em um banco de dados? Portanto, use o mesmo banco de dados para armazenar informações sobre o atual usuário / sessão.

Você pode usar o métodos mágicos __sleep() e __wakeup()

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top