2010-05-25 44 views
2

我想阻止用戶意外發表評論兩次。 我使用PRG(post重定向get)方法,以便將數據插入另一個頁面,然後將用戶重定向到顯示註釋的頁面。這允許用戶根據需要刷新多次。但是,當用戶返回並單擊再次提交或單擊提交100次時,這不起作用。我不想要100條相同的評論。有哪些方法可以防止表單中的重複發佈? (PHP)

我看了SO上的相關問題,發現一個令牌是最好的。但是我在使用它時遇到了麻煩。

//makerandomtoken(20) returns a random 20 length char. 

<form method="post" ... > 
<input type="text" id="comments" name="comments" class="commentbox" /><br/> 
<input type="hidden" name="_token" value="<?php echo $token=makerandomtoken(20); ?>" /> 
<input type="submit" value="submit" name="submit" /> 
</form> 

if (isset($_POST['submit']) && !empty($comments)) 
{ 
    $comments= mysqli_real_escape_string($dbc,trim($_POST['comments'])); 

    //how do I make the if-statment to check if the token has been already set once? 
    if (____________){ 
     //don't insert comment because already clicked submit 
    } 
    else{ 
     //insert the comment into the database 
    } 
} 

所以我有令牌作爲隱藏值,但如何使用它來防止多次點擊提交。

方法: 有人建議使用會話。我會將隨機標記設置爲$ _SESSION ['_ token']並檢查該會話標記​​是否等於$ _POST ['_ token'],但我該怎麼做?當我嘗試時,它仍然不檢查

+0

您可能要修改標題,但對問題的其餘部分不是100%準確。 – jcolebrand 2010-05-25 03:03:25

回答

0

我會跳過整個隨機標記的東西,只是在會話中存儲(散列)註釋。如果它與存儲在會話中的現有值相匹配,則放棄該評論。如果沒有,讓它通過。顯然有問題:

  • 它停止用戶在不同的地方張貼相同的評論。如果這是一個問題,請存儲評論的散列和其評論對象的ID。
  • 用戶可以按「返回」並提交不同的評論。我認爲這是一個功能(比放棄評論更好,因爲它匹配之前評論的隨機標記)。將其自動解釋爲註釋編輯並不容易。
  • 如果用戶在備用選項卡上按下「提交」,則不起作用。 (我認爲這是不可能的,而且它不需要多個隨機令牌的存儲。)

你可能想要一個隨機令牌,以防止XSRF無論如何,但這是另一個問題(在這種情況下,要確保隨機令牌與「應該是什麼」相同;我會在會話中存儲一個長壽命的令牌)。

另外,請考慮使用預準備語句。

6

如果要防止雙重提交,則必須存儲「已提交」狀態與「未提交」狀態。你有幾個選擇來保存這些信息。

  • 數據庫 - 添加隱藏字段與自動生成的值是唯一的(你可以生成一個短的隨機字符串,並追加當前時間)。此值也可用於識別對話 - 如果您需要有狀態的Web對話。將此值添加到數據庫並使其唯一。缺點:數據庫冗餘存儲,註釋插入性能下降,必須生成一個唯一的字符串。
  • 會話 - 添加相同隱藏的字段,其值類似。當用戶提交表單時,如果該表單中沒有該值,請將該值保存在會話中。如果是,那是雙重提交。缺點:您仍然需要生成唯一的令牌。
  • 瀏覽器 - (1)添加一些JavaScript以禁用點擊提交按鈕後。 (2)具有以值0開始的隱藏字段,並且當用戶單擊提交按鈕時變爲1。如果用戶再次點擊該按鈕,則檢查該值是否爲1,如果是則中止。優點:沒有獨特的字符串。缺點:需要啓用javascript;無論如何,您可能需要字符串來實現有狀態的Web對話。
+0

謝謝,我會試試看,看看我得到了什麼! – jpjp 2010-05-25 03:34:25

0

你也可以在jquery中做到這一點非常簡單。

$(document).on('click', '.className', function(){ 
    $(this).css('pointer-events', 'none'); 
});