2010-04-16 65 views
3

將表單發佈到相同的PHP頁面時,如果頁面意外刷新而不是再次提交,那麼正確的方法是什麼?

以下是我正在使用的是什麼現在:

$tmp = implode('',$_POST); 
$myHash = md5($tmp); 

if(isset($_SESSION["myHash"]) && $_SESSION["myHash"] == $myHash) 
{ 
    header("Location: index.php"); // page refreshed, send user somewhere else 
    die(); 
} 
else 
{ 
    $_SESSION["myHash"] = $myHash; 
} 

// continue processing... 

有什麼不對的解決方案?

更新:此方案的一個示例是將一行插入到註冊表中。你只會希望這個操作執行一次。

+0

如果你不介意我問,你想通過檢測$ _POST vs刷新來解決什麼問題? – 2010-04-16 01:59:16

+0

請參閱下面對Mrozek的回答的評論。檢查重複的$ _POST值告訴我,該頁面意外重新提交。 – Dieseltime 2010-04-16 03:20:41

回答

1

我一般喜歡具有POST處理程序做任何需要做的,然後將用戶重定向到一個新的頁面,

header("Location: new-page.php"); 

,使他們可以在沒有達到搞亂任何東西刷新

+0

是的,這將是顯而易見的解決方案,我這樣做基本的CRUD操作沒有問題。我想知道是否有一個可接受的解決方案來檢查表單是否被頁面刷新意外提交。 – Dieseltime 2010-04-16 03:18:57

+0

但是,如果用戶點擊返回到表單頁面並再次點擊提交,那麼最終是否會出現兩個相同的帖子? – ggfan 2010-04-17 02:46:58

+0

@ggfan:是的,但現在聽起來像*故意*行爲。 – mpen 2010-04-17 02:58:20

2

讓我們先從點,你無法區分意外刷新從有目的的刷新。所以你只能決定不允許刷新,換句話說,要求每個表單提交必須是唯一的。最好的方法是在表單中插入一個隨機標記。

<?php 
    $token = /* a randomly generated string */; 
    $_SESSION['_token'] = $token; 
?> 
<input type="hidden" name="_token" value="<?php echo $token; ?>" /> 

每次提交後,您都會使會話令牌無效。如果會話中的令牌與使用表單提交的令牌不同,則可以放棄POST。

重新評論:你可以在每個項目的基礎上做到這一點。例如,在這裏,您可能會打開幾個問題窗口並一次回答幾個問題。您可以在每個問題的基礎上製作令牌,因此用戶可以在任何時候擁有多個有效令牌,但每個問題只能有一個。

此方案的一個示例是將一行插入到註冊表中。你只會希望這個操作執行一次。

在這種情況下,您可能不應該太在意實際的POST,而應該關注數據的一致性。您應該爲每個用戶提供某種形式的唯一身份標識,例如他的電子郵件地址。如果地址已經在數據庫中註冊,則不需要再次註冊用戶。這與用戶爲什麼要嘗試註冊兩次無關(雙重提交或實際嘗試再次註冊)。

+0

當涉及多個窗口/選項卡時,需要注意的問題之一是 - 第二個選項卡覆蓋第一個選項卡的會話值,然後如果第一個選項卡被提交,令牌不再匹配。 – 2010-04-16 03:57:59

+0

@Brenton非常真實,但我會說任何以任何標準放棄POST的方法都會產生這個問題。 – deceze 2010-04-16 04:00:17

1

將標記與POST/REDIRECT/GET設計模式結合使用似乎是最好的解決方案。

  • 設置單次使用令牌將阻止用戶點擊後退按鈕並嘗試再次提交表單。
  • 重定向用戶並使用視圖來顯示輸入,可以讓他們在需要時進行刷新。