2011-01-06 22 views
12

ページを前後に移動したり、ページを更新したりして、フォームの重複を防ぐテクニックを思いつきました。そして、私はここでそれを打ち消すことを考えました、私は既に実稼働環境ではないサンプルをテストしました。あなたが識別できる欠陥は何ですか?重複したフォームの投稿を防止する

私は、CSRF攻撃からあなたを守るフォームトークンを使用していることをよく知っており、以下の手順では追加されませんでした。

各フォームの-generateフォームIDを、フォームに隠しフィールドとして使用:

$formid = microtime(true)*10000; 

- 形態でを提出:

  • 検証データ

  • から

    フォームフィールドデータのハッシュを計算する

    $allvals = ''; 
    foreach($_POST as $k=>$v){ 
        $allvals .= $v; 
    } 
    $formHash = sha1($allvals); 
    
  • 以前に保存したハッシュと比較してフォームハッシュを検証します。セッションの値は$ formid変数によって各フォームにバインドされます。

    $allowAction = true; 
    if(isset($_SESSION['formHash'][$_POST['formid']]) && ($_SESSION['formHash'][$_POST['formid']] == $formHash)){ 
        $allowAction = false; 
    } 
    
  • フォームハッシュが見つからない場合、これは送信された最初のフォームまたはフォームデータが変更されたことを意味します。
  • データは、(例えば、データベースに)保存されている場合、セッションにフォームのハッシュを保存します。

    $_SESSION['formHash'][$_POST['formid']] = $formHash; 
    

コードのフルバージョン: http://thebusy.me/2011/01/06/preventing-duplicate-form-submissions/

+0

ハッシュスニペットを '$ formHash = sha1(serialize($ _ POST));'に対してベンチマークすることを検討してください。それは有益かもしれないし、そうでないかもしれないキーをハッシュするでしょう。 – Dan

+0

おそらく関連する/ dup、http://stackoverflow.com/questions/4614052/how-to-prevent-multiple-form-submission-on-multiple-clicks-in-php/4614310#4614310 – user562374

+0

可能な重複のhttp:/ /stackoverflow.com/questions/218907/how-to-handle-multiple-submissions-server-side –

答えて

7

何を達成するための簡単な方法提出時にリダイレクトを使用することが必要です。 POSTリクエストを処理した後は、おそらく同じページにリダイレクトされます。これは、「POST後のリダイレクト」またはPOST/Redirect/GETと呼ばれる一般的なパターンです。例えば

<?php 
if($_POST) { 
    // do something 

    // now redirect 
    header("Location: " . $_SERVER["REQUEST_URI"]); 
    exit; 
} 
?> 

<html> ... 
<form method="post" action=""> ... </form> 

「」それ自体に提出するためのアクションを設定することにより、IF($ _ POST)コードブロックがリダイレクト次に、trueに検証し、フォームを処理し、その時点でそれ自体に戻る。

「フォームが送信されました」というレスポンスを表示する別のページにリダイレクトするか、フォームを別のページに置き、このページのHTMLをレスポンスにします。

この方法の利点は、戻るボタンを押すとG​​ET要求が行われるため、フォームが再送信されないことです。

Firefoxでは、実際にブラウザ履歴から自分自身に送信されるため、ユーザーがウェブをブラウズしてから戻ると、「ありがとう」ページが表示されず、フォームページが表示されます。

+0

はい、私はこれについて読んで、私は将来のプロジェクトに使用します。私の現在のウェブサイトの問題です。私はフォームトークンを使用しています。他のページにリダイレクトしてコードの構造を変更したくありません。ありがとう@ newz2000 – isogashii

+1

あなたはさらに感謝のメッセージを有効にするために一歩行くことができます。 2つのdivを設定します.1つはフォームであり、もう1つは感謝メッセージです。それから、thank you divを表示するように設定します:none in css。リダイレクトをformpage.phpに戻しますか?thankyou = 1 if($ _GET ['thankyou'] == 1){cssはフォームdivを表示しないようにして、表示していただきありがとうございます:block} – MSD

+5

This確実にフォームトークンと組み合わせる必要があります。 POST要求が進行中にユーザーがリフレッシュまたは再送信すると、重複要求が発生します。 – bcoughlan

1

これで過度に複雑になっているようです。私のお気に入りの方法、それはまた同時にハックをジャッキいくつかのセッションを防ぐために、ここで説明されています

http://www.spotlesswebdesign.com/blog.php?id=11

それはどのような形態でimplimentする、シンプルで簡単です。ランダムに生成されたページインスタンスIDを使用して、受信したフォームの提出がその特定のユーザーに配信された最後のページと同一であることを確認します。

+2

答えをくれてありがとうございますが、ポストは次のように述べています: "フォーム処理ロジックは、この周りには道があるが。同時に2つのページを開こうとすると、最初のページを送信しても、2番目のページが開かれたときに新しいページIDが生成されるので、この手法の弱点です。しかし、生成されたページIDの配列を使用してそれらをチェックし、配列から一致するものを削除することができます。 – isogashii

+0

良い点。配列は素晴らしい考えです。 – dqhendricks

+0

@isogashii配列ベースのメソッドを反映するように記事を修正しました。 – dqhendricks

-1

上記の両方の解決策は良好ですが、少し短くなります。

データのマイナーチェンジで同じユーザーからさらに数分後に挿入を停止する方法はありますか?

これは、ユーザのマシンのクッキーにmd5ハッシュを入れ、データベースにコピーを保存することで実行できます。この方法では、指定された時間内に同じマシンからの試行を無視して、データベース。

おそらく誰かが私の提案の妥当性と有効性についてコメントすることができますか、間違ったツリーを吠えますか?

関連する問題