防止表单重复提交的八种简单有效的策略
表單重復(fù)提交是在多用戶(hù)Web應(yīng)用中最常見(jiàn)、帶來(lái)很多麻煩的一個(gè)問(wèn)題。有很多的應(yīng)用場(chǎng)景都會(huì)遇到重復(fù)提交問(wèn)題,比如:
點(diǎn)擊提交按鈕兩次。
點(diǎn)擊刷新按鈕。
使用瀏覽器后退按鈕重復(fù)之前的操作,導(dǎo)致重復(fù)提交表單。
使用瀏覽器歷史記錄重復(fù)提交表單。
瀏覽器重復(fù)的HTTP請(qǐng)求。
用戶(hù)提交表單時(shí)可能因?yàn)榫W(wǎng)速的原因,或者網(wǎng)頁(yè)被惡意刷新,致使同一條記錄重復(fù)插入到數(shù)據(jù)庫(kù)中,這是一個(gè)比較棘手的問(wèn)題。我們可以從客戶(hù)端和服務(wù)器端一起著手,設(shè)法避免同一表單的重復(fù)提交。下面幫客之家收集了8種常見(jiàn)的有效防止表單重復(fù)提交的方法:來(lái)源www.bkjia.com
1、js禁掉提交按鈕。
表單提交后使用Javascript使提交按鈕disable。這種方法防止心急的用戶(hù)多次點(diǎn)擊按鈕。但有個(gè)問(wèn)題,如果客戶(hù)端把Javascript給禁止掉,這種方法就無(wú)效了。
我之前的文章曾說(shuō)過(guò)用一些Jquery插件效果不錯(cuò)。參考:js防止表單重復(fù)提交的方法和代碼
?
2、使用Post/Redirect/Get模式。
在提交后執(zhí)行頁(yè)面重定向,這就是所謂的Post-Redirect-Get (PRG)模式。簡(jiǎn)言之,當(dāng)用戶(hù)提交了表單后,你去執(zhí)行一個(gè)客戶(hù)端的重定向,轉(zhuǎn)到提交成功信息頁(yè)面。
這能避免用戶(hù)按F5導(dǎo)致的重復(fù)提交,而其也不會(huì)出現(xiàn)瀏覽器表單重復(fù)提交的警告,也能消除按瀏覽器前進(jìn)和后退按導(dǎo)致的同樣問(wèn)題。
?
3、在session中存放一個(gè)特殊標(biāo)志。
在服務(wù)器端,生成一個(gè)唯一的標(biāo)識(shí)符,將它存入session,同時(shí)將它寫(xiě)入表單的隱藏字段中,然后將表單頁(yè)面發(fā)給瀏覽器,用戶(hù)錄入信息后點(diǎn)擊提交,在服務(wù)器端,獲取表單中隱藏字段的值,與session中的唯一標(biāo)識(shí)符比較,相等說(shuō)明是首次提交,就處理本次請(qǐng)求,然后將session中的唯一標(biāo)識(shí)符移除;不相等說(shuō)明是重復(fù)提交,就不再處理。
這使你的web應(yīng)用有了更高級(jí)的XSRF保護(hù)。
請(qǐng)見(jiàn)如下代碼:
4.使用header函數(shù)轉(zhuǎn)向
除了上面的方法之外,還有一個(gè)更簡(jiǎn)單的方法,那就是當(dāng)用戶(hù)提交表單,服務(wù)器端處理后立即轉(zhuǎn)向其他的頁(yè)面,代碼如下所示。
if (isset($_POST['action']) && $_POST['action'] == 'submitted') {
//處理數(shù)據(jù),如插入數(shù)據(jù)后,立即轉(zhuǎn)向到其他頁(yè)面
header('location:submits_success.php');
}
這樣,即使用戶(hù)使用刷新鍵,也不會(huì)導(dǎo)致表單的重復(fù)提交,因?yàn)橐呀?jīng)轉(zhuǎn)向新的頁(yè)面,而這個(gè)頁(yè)面腳本已經(jīng)不理會(huì)任何提交的數(shù)據(jù)了。
5.表單過(guò)期的處理
在開(kāi)發(fā)過(guò)程中,經(jīng)常會(huì)出現(xiàn)表單出錯(cuò)而返回頁(yè)面的時(shí)候填寫(xiě)的信息全部丟失的情況,為了支持頁(yè)面回跳,可以通過(guò)以下兩種方法實(shí)現(xiàn)。
1.使用header頭設(shè)置緩存控制頭Cache-control。
header('Cache-control: private, must-revalidate'); //支持頁(yè)面回跳
2.使用session_cache_limiter方法。
session_cache_limiter('private, must-revalidate'); //要寫(xiě)在session_start方法之前
下面的代碼片斷可以防止用戶(hù)填寫(xiě)表單的時(shí)候,單擊“提交”按鈕返回時(shí),剛剛在表單上填寫(xiě)的內(nèi)容不會(huì)被清除:
session_cache_limiter('nocache');
session_cache_limiter('private');
session_cache_limiter('public');
session_start();
//以下是表單內(nèi)容,這樣在用戶(hù)返回該表單時(shí),已經(jīng)填寫(xiě)的內(nèi)容不會(huì)被清空
將該段代碼貼到所要應(yīng)用的腳本頂部即可。
Cache-Control消息頭域說(shuō)明
Cache-Control指定請(qǐng)求和響應(yīng)遵循的緩存機(jī)制。在請(qǐng)求消息或響應(yīng)消息中設(shè)置Cache-Control并不會(huì)修改另一個(gè)消息處理過(guò)程中的緩存處理過(guò)程。
請(qǐng)求時(shí)的緩存指令包括no-cache、no-store、max-age、max-stale、min-fresh和only-if-cached,響應(yīng)消息中的指令包括public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate和max-age。各個(gè)消息中的指令含義如表5-3所示。
表5-3
緩存指令 | 說(shuō)?明 |
public | 指示響應(yīng)可被任何緩存區(qū)緩存 |
private | 指示對(duì)于單個(gè)用戶(hù)的整個(gè)或部分響應(yīng)消息,不能被共享緩存處理。這允許服務(wù)器僅僅描述當(dāng)用戶(hù)的部分響應(yīng)消息,此響應(yīng)消息對(duì)于其他用戶(hù)的請(qǐng)求無(wú)效 |
no-cache | 指示請(qǐng)求或響應(yīng)消息不能緩存 |
no-store | 用于防止重要的信息被無(wú)意的發(fā)布。在請(qǐng)求消息中發(fā)送將使得請(qǐng)求和響應(yīng)消息都不使用緩存 |
max-age | 指示客戶(hù)機(jī)可以接收生存期不大于指定時(shí)間(以秒為單位)的響應(yīng) |
min-fresh | 指示客戶(hù)機(jī)可以接收響應(yīng)時(shí)間小于當(dāng)前時(shí)間加上指定時(shí)間的響應(yīng) |
max-stale | 指示客戶(hù)機(jī)可以接收超出超時(shí)期間的響應(yīng)消息。如果指定max-stale消息的值,那么客戶(hù)機(jī)可以接收超出超時(shí)期指定值之內(nèi)的響應(yīng)消息 |
有關(guān)Session和Cookie的介紹,詳細(xì)內(nèi)容請(qǐng)參閱第10章“PHP會(huì)話管理”。
6.判斷表單動(dòng)作的技巧
表單可以通過(guò)同一個(gè)程序來(lái)分配應(yīng)該要處理的動(dòng)作,在表單中有不同的邏輯,要怎么判別使用者按下的按鈕內(nèi)容不過(guò)是個(gè)小問(wèn)題。
其實(shí)只要通過(guò)提交按鈕的name 就可以知道了,表單在提交出去的時(shí)候,只有按下的submit類(lèi)型的按鈕才會(huì)被送到表單數(shù)組去,所以只要判斷按鈕的值就可以知道使用者按下哪一個(gè)按鈕,以如下表單為例:
<FORM method="POST" Action=test.php>
<input type=submit name="btn" value="a">
<input type=submit name="btn" value="b">
</FORM>
當(dāng)使用者按下“a”按鈕的時(shí)候btn=a,按下“b”按鈕,則btn=b。
另外也可以通過(guò)提交按鈕的名字(name)來(lái)判斷,請(qǐng)見(jiàn)如下代碼:
<FORM method="POST" Action=test.php>
<input type=submit name="a" value="提交A">
<input type=submit name="b" value="提交B">
</FORM>
這樣只要POST/GET的參數(shù)里面有a或b,就可以知道按下的按鈕是哪個(gè)。
<?php
print_r($_POST);
?>
?
7、在數(shù)據(jù)庫(kù)里添加約束。
在數(shù)據(jù)庫(kù)里添加唯一約束或創(chuàng)建唯一索引,防止出現(xiàn)重復(fù)數(shù)據(jù)。這是最有效的防止重復(fù)提交數(shù)據(jù)的方法。
你是如何克服數(shù)據(jù)重復(fù)提交問(wèn)題的?你遇到過(guò)什么重復(fù)提交數(shù)據(jù)的現(xiàn)實(shí)例子嗎?
轉(zhuǎn)載自:http://www.bkjia.com/jingyan/471187.html
5.使用客戶(hù)端腳本
提到客戶(hù)端腳本,經(jīng)常使用的是JavaScript進(jìn)行常規(guī)輸入驗(yàn)證。在下面的例子中,我們使用它處理表單的重復(fù)提交問(wèn)題,請(qǐng)看下面的代碼:
<form method="post" name="register" action="test.php" enctype="multipart/form-data">
<input name="text" type="text" id="text" />
<input name="cont" value="提交" type="button" onClick="document.register.cont.value='正在提交,請(qǐng)等待...';document.register.cont.disabled=true;document.the_form.submit();">
</form>
當(dāng)用戶(hù)單擊“提交”按鈕后,該按鈕將變?yōu)榛疑豢捎脿顟B(tài)。
上面的例子中使用OnClick事件檢測(cè)用戶(hù)的提交狀態(tài),如果單擊了“提交”按鈕,該按鈕立即置為失效狀態(tài),用戶(hù)不能單擊按鈕再次提交。
?
8.使用Cookie處理
使用Cookie記錄表單提交的狀態(tài),根據(jù)其狀態(tài)可以檢查是否已經(jīng)提交表單,請(qǐng)見(jiàn)下面的代碼:
<?php
if(isset($_POST['go'])){
setcookie("tempcookie","",time()+30);
header("Location:".$_SERVER[PHP_SELF]);
exit();
}
if(isset($_COOKIE["tempcookie"])){
setcookie("tempcookie","",0);
echo "您已經(jīng)提交過(guò)表單";
}
?>
如果客戶(hù)端禁止了Cookie,該方法將不起任何作用,這點(diǎn)請(qǐng)注意。關(guān)于Cookie的詳細(xì)介紹,請(qǐng)參閱第10章“PHP會(huì)話管理”。
PS:這幾種防止重復(fù)提交表單的方法可以做參考,自己使用過(guò)第一種方式來(lái)防止表單多次提交。
來(lái)源幫客之家收集整理,轉(zhuǎn)載請(qǐng)注明出處:www.bkjia.com/jingyan/
總結(jié)
以上是生活随笔為你收集整理的防止表单重复提交的八种简单有效的策略的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 分享PowerMill数控编程应用技巧,
- 下一篇: 车机如何安装鸿蒙os,跨平台的鸿蒙OS,