0

セッションがタイムアウトするまでフォームを開いたままにする可能性のあるユーザーを支援するために、ログインページから送信されてフォームにリダイレクトされた後、フォームを再送信しようとしています。このサイトには数十のフォームがあるので、これを汎用にして親フォームに適用して、すべてがこの機能を利用できるようにしたいと考えています。

現在、フォームを送信しようとして認証が見つからない場合 (つまり、セッションがタイムアウトしたか、テスト目的で別のタブからログアウトした場合)、次のように投稿パラメーターとリファラー URL を保持するログイン ページに送信されます。

 $this->getUser()->setAttribute('referer', $this->getRequest()->getUri());
 $this->getUser()->setAttribute('postparameters', $this->getRequest()->getPostParameters());

次に、ログインに成功すると、URL にリダイレクトされます。

 $this->redirect($this->getUser()->getAttribute('referer', '@homepage'));

これはリダイレクトであり、http GET 要求が発生するため、ここで投稿パラメーターを復元することはできません。代わりに、フォームが処理されようとしているアクションにこのコードを入れました

$postparams = $this->getUser()->getAttribute('postparameters');
if (is_array($postparams))
{
    foreach($postparams as $key => $postparam)
    {
        $request->setParameter($key, $postparam);
    }
} 

ただし、投稿パラメーターには前のセッションの _csrf_token が含まれており、フォームは検証に失敗します。$postparams 配列からその項目を削除すると、トークンが必要なため、フォームは拒否されます。CSRF 保護を完全に無効にしたくはありませんが、それを回避する方法を見つけることができます。

4

1 に答える 1

0

私が今持っている解決策は、フォームが無効であることが判明し、再描画されようとしている後に新しいCSRFトークンを生成することです

public function executeUpdate(sfWebRequest $request)
{

    ...

    if ($this->largePlantForm->isValid())
    {
        ....
    } else {        
        $tempform = new largePlantForm();
        $this->largePlantForm->setValue($tempform->getCSRFFieldName(), $tempform->getCSRFToken());
        $this->setTemplate('edit');
} 

これは、setValue() を追加する BaseForm への変更に依存しています。フォームが無効であると宣言された後にこれを呼び出す理由は、事前にこれを行うと、csrf_token が常に有効になり、無価値になることを意味するからです。私の方法では、ユーザーはログイン ページに誘導される前に使用していたフォームに戻され、値がすべてそこにあるため、ユーザーはページを確認し、新しい csrf_token と一緒に送信する必要があります。

于 2013-09-04T03:01:17.937 に答える