2009-10-29 80 views
4

當用戶點擊「返回」按鈕時,阻止表單被重新處理的最佳方式是什麼?PHP:按下「返回」按鈕時阻止表單被意外重新處理

我正在關注Post/Redirect/Get pattern,所以如果按F5鍵,我沒有問題,但後退按鈕仍然提供重新提交表單的機會。如果這個表單是一個信用卡處理頁面,這是不好的。

這個問題已被問到有些here,但措辭和答案質量差,並不完全具體到這個問題。

我有form.php提交給自己。如果輸入數據在提交時沒有錯誤,用戶將被重定向到form_thanks.php。一旦重新提交form.php(BAD!),然後將它們帶回form_thanks.php,就會返回(和「發送」或「重新提交」)。

如果可能,還請包括不涉及使用會話的解決方案。

+0

你爲什麼要實現這一點沒有會話?您可能需要*某種*服務器端存儲來檢測重複的帖子。 – staticsan 2009-10-29 23:40:41

+0

請參閱下面的內容,我建議將令牌存儲在數據庫中以及是否使用它。這絕對是*某種*服務器端存儲,但不是會話。 – 2009-10-30 00:19:46

回答

2

這應該使用一次性令牌或nonce。 php/server應該在隱藏的表單域中包含這個標記。

它應該存儲所有最近令牌的列表,並且每次提交表單時,都應檢查該令牌是否在最近有效令牌的列表中。

如果它不在列表中,則不要重新處理表單。
如果它在列表中,則處理表單並從列表中刪除標記。

令牌可以在會話中處理,也可以在沒有會話的簡單數據庫表中處理。令牌應該是用戶特定的。

這也是避免CSRF攻擊的推薦方法。

+0

嗯,我很驚訝你可以回答你自己的問題。最有可能只是「更新」你的主要問題來包含解決方案。 – Jakub 2009-11-17 21:10:21

+0

「問問並回答你自己的問題也很好」(http://meta.stackoverflow.com/faq),有人建議我這樣做,一旦別人的回答似乎沒有完全回答這個問題。最好在不同的問題/答案中這樣做,因爲這樣其他人可以專門對他們發表評論/投票,否則原來的「問題」讓那些發現問題的人感到困惑,因爲它不再是一個問題。 – philfreo 2009-11-18 00:27:40

0

我發現後面會將窗體帶到頁面被重定向之前的狀態,如果是這樣的話,有一個隱藏的輸入/變量或者以value開頭的東西,那麼一旦表單被提交,如果該值爲true,則將其更改爲false,然後提交,否則返回false

+0

你能否確認這在所有瀏覽器中以相同的方式工作? – philfreo 2009-10-29 22:56:04

7

我會以不同的方式執行此操作。建立一個隱藏的輸入,其中隨機字符串作爲值,並在提交時將該隨機字符串存儲在會話中。設置一個簡單的檢查,看看他們是否已經發布了它,如果他們不接受輸入。

1

想想這裏大聲。但是關於post/redirect/get的變體怎麼樣,最終的get並不是最終的get;)但是,它總是自動轉發到真正的最終頁面,所以如果用戶點擊後退按鈕,它們會返回他們從哪裏來的?

編輯:

好吧,考慮到OP的評論,這裏的另一個想法。表單提交的URL可能需要一個僅適用於一種用途的參數。該表單在提交表單之前會被生成(使用MD5或其他類似方式),並且可以存儲在數據庫中(以響應別人的建議而不使用會話請求解決方案)。表單處理完成後,該標記將在數據庫中標記爲已被使用。因此,當頁面以相同的標記返回時,可以採取措施防止表單數據重新提交到後端。

+0

除了瀏覽器的後退按鈕通常有下拉菜單,用戶可以輕鬆跳回2頁或更多頁以外,這種方式會起作用。 – philfreo 2009-10-29 23:56:44

+0

根據我的第二個建議,每次請求的URL沒有標記參數時,就會生成一個標記,表單本質上會重定向到它本身,但是將此標記作爲URL的一部分。希望這是有道理的,我自5:30起就一直在上;) – 2009-10-30 00:32:26

+0

是的,這個第二個解決方案聽起來不錯。 – philfreo 2009-10-30 03:35:45

1

最新答案,但可以通過使用基於AJAX的解決方案完全避免處理;使用此處理方案包含一個隨機數不會有問題,但通過使用異步查詢,在成功時重定向用戶,請求不會通過刷新,按回或除點擊按鈕之外的任何操作重複。

也很容易實現一種機制,可以防止按鈕被按下兩次,或者在請求期間發生的事情通過嵌入到請求的處理程序中而被「鎖定」(無論是使用PrototypeJS還是jQuery的高級別或低級別與您的手動功能)分別在請求完成和第一次觸發時啓用和禁用按鈕的機制。

+0

這也有很多意義 – philfreo 2009-11-18 00:30:42

-1

試試這個:

<SCRIPT type="text/javascript"> 
    window.history.forward(); 
</SCRIPT> 
+0

這是一個PHP問題,而不是JavaScript。 – 2012-10-02 08:05:26

+0

這不提供問題的答案。要批評或要求作者澄清,在他們的帖子下留下評論 - 你可以隨時評論你自己的帖子,一旦你有足夠的[聲譽](http://stackoverflow.com/faq#reputation),你將能夠[評論任何帖子](http://stackoverflow.com/privileges/comment)。 – 2012-10-02 08:05:40

+0

我已經在我的在線考試頁面(** PHP **)嘗試了上面的代碼。其中阻止了後退按鈕的操作,我知道它違反了禁用後退按鈕的規則。如果候選人可以回頭再回答問題(在線考試的情況下),這是沒有意義的。它爲我工作。 – zphp 2012-10-03 04:29:04