中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

web中如何處理重復提交、重復刷新、防止后退的問題

發布時間:2021-10-13 14:08:16 來源:億速云 閱讀:241 作者:小新 欄目:移動開發

這篇文章主要介紹web中如何處理重復提交、重復刷新、防止后退的問題,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

一。前言
你在任何一個比較專業的BBS都會看到這樣的問題,即使你Google一下,也會發現有很多的人在關注和詢問,但大家給出的解決方法卻都是千差萬別,(有的人主張采用腳本來解決;有的則想重定向到別的頁面;有的則將此問題提升到Token的角度)為什么會有如此大的差異呢?
二。問題場景
首先,我們應該先了解為什么要處理這樣的問題?或者專業一點就是它適合的場景是什么?(似乎只有人來問沒有人來解釋)
1。重復提交、重復刷新的場景
重復提交、重復刷新都是來解決系統重復記錄的問題。也就是說某個人在多次的提交某條記錄(為什么?也許是閑了沒有事情干的;最有可能是用戶根本就不知道自己的提交結果是否已經執行了?!)。
但出現了這樣的問題并不見得就必須處理,要看你所開發的系統的類別而定。比如你接手的是某個資源管理系統,系統本身從需求的角度根本就不允許出現"重復"的記錄,在這樣需求的約束條件下,去執行重復的提交動作只會引發“業務級異常”的產生,根本就不可能執行成功也就無所謂避免不避免的問題了。
2。防止后退的場景
了解了重復刷新、重復提交的場景,我們來了解一下"防止后退"操作的原因是什么?比如你在開發某個投票系統,它有很多的步驟,并且這些步驟之間是有聯系的,比如第一步會將某些信息發送給第二步,第二步緩存了這些信息,同時將自身的信息發送給了第三步。。。。。等等,如果此時用戶處在第三步驟下,我們想象一下某個淘氣用戶的用戶點擊了后退按鈕,此時屏幕出現了第二步驟的頁面,他再次的修改或者再次的提交,進入到下一個步驟(也就是第三步驟),錯誤就會在此產生?!什么錯誤呢?最為典型的就是這樣的操作直接導致了對于第一個步驟信息的丟失!(如果這樣的信息是依靠Request存放的話,當然你可以存放在Session或者更大的上下文環境中,但這不是個好主意!關于信息存放的問題,下次在就這個問題詳細的討論)
三。如何處理的問題
當然很多的系統(比如訂票系統從需求上本身是允許個人重復訂票的)是必須要避免重復刷新、重復提交、以及防止后退的問題的,但即使是這樣的問題,也要區分如何處理以及在哪里處理的(網上只是告訴你如何處理,但很少去區分在哪里處理的),顯然處理的方式無非是客戶端或者服務器端兩種,而面對不同的位置處理的方式也是不同的,但有一點要事先聲明:任何客戶端(尤其是B/S端)的處理都是不可信任的,最好的也是最應該的是服務器端的處理方法。
客戶端處理:
面對客戶端我們可以使用Javascript腳本來解決,如下
1。重復刷新、重復提交
Ways One:設置一個變量,只允許提交一次。

代碼如下:


<script language="javascript">
var checkSubmitFlg = false;
function checkSubmit() {
if (checkSubmitFlg == true) {
return false;
}
checkSubmitFlg = true;
return true;
}
document.ondblclick = function docondblclick() {
window.event.returnValue = false;
}
document.onclick = function doc {
if (checkSubmitFlg) {
window.event.returnValue = false;
}
}
</script>
<html:form action="myAction.do" method="post" onsubmit="return checkSubmit();">
Way Two : 將提交按鈕或者image置為disable
<html:form action="myAction.do" method="post"
onsubmit=" getElById_r('submitInput').disabled = true; return true;">
<html:image styleId="submitInput" src="images/ok_b.gif" border="0" />
</html:form>


2。防止用戶后退
這里的方法是千姿百態,有的是更改瀏覽器的歷史紀錄的,比如使用window.history.forward()方法;有的是“用新頁面的URL替換當前的歷史紀錄,這樣瀏覽歷史記錄中就只有一個頁面,后退按鈕永遠不會變為可用。”比如使用javascript:location.replace(this.href); event.returnValue=false;

2.服務器端的處理(這里只說Struts框架的處理)
利用同步令牌(Token)機制來解決Web應用中重復提交的問題,Struts也給出了一個參考實現。
基本原理:
服務器端在處理到達的請求之前,會將請求中包含的令牌值與保存在當前用戶會話中的令牌值進行比較,
看是否匹配。在處理完該請求后,且在答復發送給客戶端之前,將會產生一個新的令牌,該令牌除傳給
客戶端以外,也會將用戶會話中保存的舊的令牌進行替換。這樣如果用戶回退到剛才的提交頁面并再次
提交的話,客戶端傳過來的令牌就和服務器端的令牌不一致,從而有效地防止了重復提交的發生。
if (isTokenValid(request, true)) {
// your code here
return mapping.findForward("success");
} else {
saveToken(request);
return mapping.findForward("submitagain");
}
Struts根據用戶會話ID和當前系統時間來生成一個唯一(對于每個會話)令牌的,具體實現可以參考
TokenProcessor類中的generateToken()方法。
1. //驗證事務控制令牌,<html:form >會自動根據session中標識生成一個隱含input代表令牌,防止兩次提交
2. 在action中:

//<input type="hidden" name="org.apache.struts.taglib.html.TOKEN"
// value="6aa35341f25184fd996c4c918255c3ae">
if (!isTokenValid(request))
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("error.transaction.token"));
resetToken(request); //刪除session中的令牌
3. action有這樣的一個方法生成令牌
protected String generateToken(HttpServletRequest request) {
HttpSession session = request. getSession_r();
try {
byte id[] = session. getId_r(). getBytes_r();
byte now[] =
new Long(System.currentTimeMillis()).toString(). getBytes_r();
MessageDigest md = MessageDigest. getInstance_r("MD5");
md.update(id);
md.update(now);
return (toHex(md.digest()));
} catch (IllegalStateException e) {
return (null);
} catch (NoSuchAlgorithmException e) {
return (null);
}
}
總結
對于重復提交、重復刷新、防止后退等等都是屬于系統為避免重復記錄而需要解決的問題,在客戶端去處理需要針對每一種的可能提出相應的解決方案,然而在服務器端看來只不過是對于數據真實性的檢驗問題,基于令牌的處理就是一勞永逸的方法。
同時我們也看到,從不同的角度去看待問題,其解決的方法也是不同的。客戶端更追求的是用戶的操作,而服務端則將注意力放在了數據的處理上,所以在某個對于服務器端看似容易的問題上,用客戶端來解決卻麻煩了很多!反之依然。所以在某些問題的處理上我們需要綜合考慮和平衡,是用客戶端來解決?還是用服務器端來處理?
 
網頁防刷新重復提交、防后退解決方法
提交后禁用提交按鈕(大部分人都是這樣做的)
如果客戶提交后,按F5刷新怎么辦?
使用Session
在提交的頁面也就是數據庫處理之前:
if session("ok")=true then
response.write "錯誤,正在提交"
response.end
end if
數據處理完后,修改session("ok")=false。
數據處理成功馬上Redirect到另外一個頁面
操作后刷新的確是個問題,你可以使用跳轉頁面、關閉本頁面,如果是有參數據條件來控制的,那就應該好做了,可以直接修改window.location的值,把參數全部改掉,這樣就差不多了。
缺點:簡單地運用Response.Redirect將不再有效,因為用戶從一個頁面轉到另一個頁面,我們都必須用客戶端代碼清除location.history。注意,這種方法清除的是最后一個訪問歷史記錄,而不是全部的訪問記錄。點擊后退按鈕,再點擊后退按鈕,你可以看到這時打開的是本頁面之前的頁面!(當然,這是在你的客戶端啟用了JavaScript功能的條件下。)
如果客戶按后退,怎么辦?

防止網頁后退--禁止緩存
我們在進行數據庫添加操作的時候,如果允許后退,而正巧有刷新了頁面,就會再次執行添加操作,無疑這不是我們需要的,像一般網上很多禁止緩存的代碼,有時并不可靠,這時你只要在操作的頁面加上就可以了,在網頁的里指定要定向的新頁,再點后退,看是不是不會再退到剛才的操作頁面了,實際上已經把這個歷史給刪除了
ASP:
Response.Buffer = True
Response.ExpiresAbsolute = Now() - 1
Response.Expires = 0
Response.CacheControl = "no-cache"
ASP.NET:
Response.Buffer=true;
Response.ExpiresAbsolute=DateTime.Now.AddSeconds(-1);
Response.Expires=0;
Response.CacheControl="no-cache";
究竟怎樣才能"禁用"瀏覽器的后退按鈕?或者“怎樣才能防止用戶點擊后退按鈕返回以前瀏覽過的頁面?”
遺憾的是,我們無法禁用瀏覽器的后退按鈕。
防止網頁后退--新開窗口
用window.open彈出表單頁面,點提交后關閉該頁;處理提交的ASP頁也是用彈出,設定表單的target,點提交時window.open("XXX.asp","_blank"),然后用JS來提交表單,完成后window.close();
簡單的說,就是提交表單的時候彈出新窗口,關閉本窗口。對于window.open()打開的窗口怎么后退?能后退到哪里去?
呵呵,羅嗦了一堆廢話,知道怎么處理了么?混合運用客戶端腳本和服務器端腳本。
 
jsp重復提交問題
看了網上的,有幾種方法:
1 在你的表單頁里HEAD區加入這段代碼:
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
<META HTTP-EQUIV="expires" CONTENT="Wed, 26 Feb 1997 08:21:57 GMT">
2
生成一個令牌保存在用戶session中,在form中加一個hidden域,顯示該令
牌的值,form提交后重新生成一個新的令牌,將用戶提交的令牌和session
中的令牌比較,如相同則是重復提交
3
在你的服務器端控件的代碼中使用Response.Redirect("selfPage")語句。但是大多的數都不使用這種方法。
方法還有很多。。。
4
<input type="button" value="提交" onclick="this.disabled=true;this.form.submit()">
5
在JSP頁面的FORM表單中添加一個hidden域
<input type="hidden" name="url"value=<%=request. getRequestURL_r()%>>

在你的serverlet中添加如下語句
String url=request. getParameter_r("url");
response.sendRedirect(url);
我一般都是采用這樣的方法返回JSP頁面的,不太明白你說的重復刷新是什么概念
6 ajax 無刷新提交
7 Web開發中防止瀏覽器的刷新鍵引起系統操作重復提交
怎么解決呢?重定向可以解決頁面刷新帶來的數據的重復提交的問題,我們自然可以利用重定向的方式來解決這個問題。但是struts的action里面mapping.findword();跳轉的話,默認的是在工程文件夾里面找要跳轉的頁面。這種情況,怎么解決呢?
修改struts-config.xml 文件,在action里面有一個redirect重新定向的屬性,struts中默認的是false,添加這個屬性,改成true,在forword中寫上要跳轉頁面的絕對或者相對地址就行了
修改如下:
<action-mappings>
<action attribute="newsActionForm" name="newsActionForm"
input="/addnews.jsp" path="/newsAction" parameter="method"
scope="request" type="com.yongtree.news.action.NewsAction">
<forward name="list" path="/listnews.jsp" redirect="true"></forward>
<forward name="error" path="/addnews.jsp"></forward>
</action>
</action-mappings>

瀏覽器相關難處理的問題
瀏覽器的后退按鈕使得我們能夠方便地返回以前訪問過的頁面,它無疑非常有用。但有時候我們不得不關閉這個功能,以防止用戶打亂預定的頁面訪問次序。本文介紹網絡上可找到的各種禁用瀏覽器后退按鈕方案,分析它們各自的優缺點和適用場合。
一、概述

   曾經有許多人問起,“怎樣才能&lsquo;禁用&rsquo;瀏覽器的后退按鈕?”,或者“怎樣才能防止用戶點擊后退按鈕返回以前瀏覽過的頁面?”在ASP論壇上,這個問題也是問得最多的問題之一。遺憾的是,答案非常簡單:我們無法禁用瀏覽器的后退按鈕。
   起先我對于居然有人想要禁用瀏覽器的后退按鈕感到不可思議。后來,看到竟然有那么多的人想要禁用這個后退按鈕,我也就釋然(想要禁用的只有后退按鈕,不包括瀏覽器的前進按鈕)。因為在默認情況下,用戶提交表單之后可以通過后退按鈕返回表單頁面(而不是使用“編輯”按鈕!),然后再次編輯并提交表單向數據庫插入新的記錄。這是我們不愿看到的。
   因此我就決定要找出避免出現這種情況的方法。我訪問了許多網站,參考了這些網站所介紹的各種實現方法。如果你經常訪問ASP編程網站,本文所介紹的部分內容你可能已經見到過。本文的任務是把各種可能的方法都介紹給大家,然后找出最好的方法!
二、禁止緩存
   在我找到的許多方案中,其中有一種建議禁止頁面緩存。具體是使用服務器端腳本,如下所示:
<%
Response.Buffer = True
Response.ExpiresAbsolute = Now() - 1
Response.Expires = 0
Response.CacheControl = "no-cache"
%>
   這種方法非常有效!它強制瀏覽器重新訪問服務器下載頁面,而不是從緩存讀取頁面。使用這種方法時,編程者的主要任務是創建一個會話級的變量,通過這個變量確定用戶是否仍舊可以查看那個不適合通過后退按鈕訪問的頁面。由于瀏覽器不再緩存這個頁面,當用戶點擊后退按鈕時瀏覽器將重新下載該頁面,此時程序就可以檢查那個會話變量,看看是否應該允許用戶打開這個頁面。

   例如,假設我們有如下表單:

<%
Response.Buffer = True
Response.ExpiresAbsolute = Now() - 1
Response.Expires = 0
Response.CacheControl = "no-cache"
If Len(Session("FirstTimeToPage")) > 0 then
&single; 用戶已經訪問過當前頁面,現在是再次返回訪問。
&single; 清除會話變量,將用戶重定向到登錄頁面。
Session("FirstTimeToPage") = ""
Response.Redirect "/Bar.asp"
Response.End
End If
&single; 如果程序運行到這里,說明用戶能夠查看當前頁面
&single; 以下開始創建表單
%>
<form method=post action="SomePage.asp">
<input type=submit>
</form>

   我們借助會話變量FirstTimeToPage檢查用戶是否是第一次訪問當前頁面。如果不是第一次(即Session("FirstTimeToPage")包含某個值),那么我們就清除會話變量的值,然后把用戶重新定向到一個開始頁面。這樣,當表單提交時(此時SompePage.asp被打開),我們必須賦予FirstTimeToPage一個值。即,在SomePage.asp中我們需要加上下面的代碼:
Session("FirstTimeToPage") = "NO"
   這樣,已經打開SomePage.asp的用戶如果點擊后退按鈕,瀏覽器將重新請求服務器下載頁面,服務器檢查到Session("FirstTimeToPage")包含了一個值,于是就清除Session("FirstTimeToPage"),并把用戶重定向到其他頁面。當然,所有這一切都需要用戶啟用了Cookie,否則會話變量將是無效的。(有關該問題的更多說明,請參見For session ariables to work, must the Web visitor have cookies enabled?)
   另外,我們也可以用客戶端代碼使瀏覽器不再緩存Web頁面:
<html>
<head>
<meta http-equiv="Expires" CONTENT="0">
<meta http-equiv="Cache-Control" CONTENT="no-cache">
<meta http-equiv="Pragma" CONTENT="no-cache">
</head>
   如果使用上面的方法強制瀏覽器不再緩存Web頁面,必須注意以下幾點:

只有在使用安全連接時“Pragma: no-cache”才防止瀏覽器緩存頁面。對于不受安全保護的頁面,“Pragma: no-cache”被視為與“Expires: -1”相同,此時瀏覽器仍舊緩存頁面,但把頁面標記為立即過期。在IE 4或5中,“Cache-Control”META HTTP-EQUIV標記將被忽略,不起作用。
   在實際應用中我們可以加上所有這些代碼。然而,由于這種方法不能適用于所有的瀏覽器,所以是不推薦使用的。但如果是在Intranet環境下,管理員可以控制用戶使用哪種瀏覽器,我想還是有人會使用這種方法。
三、其他方法

   接下來我們要討論的方法以后退按鈕本身為中心,而不是瀏覽器緩存。這兒有一篇文章Rewiring the Back Button很值得參考。不過我注意到,如果使用這種方法,雖然用戶點擊一下后退按鈕時他不會看到以前輸入數據的頁面,但只要點擊兩次就可以,這可不是我們希望的效果,因為很多時候,固執的用戶總是能夠找到繞過預防措施的辦法。
   另外一種禁用后退按鈕的辦法是用客戶端JavaScript打開一個沒有工具條的窗口,這使得用戶很難返回前一頁面,但不是不可能。一種更安全但相當惱人的方法是,當表單提交時打開一個新的窗口,與此同時關閉表單所在的窗口。但我覺得這種方法不值得認真考慮,因為我們總不能讓用戶每提交一個表單就打開一個新窗口。
   那么,在那個我們不想讓用戶返回的頁面是否也可以加入JavaScript代碼呢?在這個頁面中加入的JavaScript代碼可用來產生點擊前進按鈕的效果,這樣也就抵消了用戶點擊后退按鈕所產生的動作。用于實現該功能的JavaScript代碼如下

所示:
<script language="JavaScript">
<!--
javascript:window.history.forward(1);
//-->
</script>
   同樣地,這種方法雖然有效,但距離“最好的方法”還差得很遠。后來我又看到有人建議用location.replace從一個頁面轉到另一個頁面。這種方法的原理是,用新頁面的URL替換當前的歷史紀錄,這樣瀏覽歷史記錄中就只有一個頁面,后退按鈕永遠不會變為可用。我想這可能正是許多人所尋求的方法,但這種方法仍舊不是任何情況下的最好方法。使用這種方法的實例如下所示:
<A HREF="PageName.htm" onclick="javascript:location.replace(this.href);
event.returnValue=false;">禁止后退到本頁面的鏈接</A>
   禁止后退到本頁面的鏈接!
   這種方法的缺點在于:簡單地運用Response.Redirect將不再有效,這是因為每次用戶從一個頁面轉到另一個頁面,我們都必須用客戶端代碼清除location.history。另外還要注意,這種方法清除的是最后一個訪問歷史記錄,而不是全部的訪問記錄。
   點擊上面的鏈接,你將打開一個簡單的HTML頁面。再點擊后退按鈕,你可以看到這時打開的不是本頁面,而是本頁面之前的頁面!(當然,你必須在瀏覽器中啟用了客戶端JavaScript代碼。)
   經過一番仔細的尋尋覓覓之后,我發現仍舊無法找出真正能夠完全禁用瀏覽器后退按鈕的辦法。所有這里介紹的方法都能夠在不同程度上、以不同的方式禁止用戶返回前一頁面,但它們都有各自的局限。由于不存在能夠完全禁用后退按鈕的方法,所以最好的方案應該是:混合運用客戶端腳本和服務器端腳本。

<html>
<head>
<meta http-equiv="Expires" CONTENT="0">
<meta http-equiv="Cache-Control" CONTENT="no-cache">
<meta http-equiv="Pragma" CONTENT="no-cache">
</head>
<script language="JavaScript">
<!--
javascript:window.history.forward(1);
//-->
</script>
</html>
Asp.net中防刷新重復提交、防后退方法
簡單操作方法防后退和刷新
Page_Load中加入
Response.Cache.SetNoStore();
//Session中存儲的變量“IsSubmit”是標記是否提交成功的
if (!IsPostBack)
if (Session["IsSubmit"]==null)
Session.Add("IsSubmit",false);
if ((bool)Session["IsSubmit"])
{
//如果表單數據提交成功,就設“Session["IsSubmit"]”為false
Session["IsSubmit"] = false;
//顯示提交成功信息
TextBox1.Text = " * 提交成功!";
}
else
{//否則的話(沒有提交,或者是頁面刷新),不顯示任何信息
TextBox1.Text = "";
Response.End();
}
提交按鈕中加入
Session["IsSubmit"] = true;
Response.Redirect ("本頁");

另外:
1、通常應該在業務層進行判斷(唯一性)解決這種問題
2、要在頁面裝載事件寫上 Response.CacheControl = "no-cache" 清除緩存
3、也有人這樣說:我以前也碰到過這樣的問題,是在分步提交中一個人的簡歷,在寫完第一個頁面后跳到第二個頁面,為了防止用戶用后退返回到第一個頁面,再重新提交第一個頁面,我是當用戶提交第一次提交第一個頁面時,把插入數據庫中的記錄的自增長id號放到session里,當用戶從第二個頁面返回到第一個頁面再一次提交該頁面時,我就用session里的值去數據庫查,如果有這個id就用update語句把第一個頁面的數據寫進數據庫,如果沒有查到這個id,就用insert語句。

以上是“web中如何處理重復提交、重復刷新、防止后退的問題”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

web
AI

玉林市| 岚皋县| 玛沁县| 邳州市| 凤阳县| 丘北县| 寿光市| 上思县| 岳阳市| 车险| 贵阳市| 德化县| 富宁县| 苏尼特右旗| 红安县| 皮山县| 杭锦旗| 铁力市| 北流市| 西畴县| 都匀市| 浦县| 凭祥市| 隆昌县| 濉溪县| 昌邑市| 大庆市| 黑山县| 和硕县| 黄平县| 松阳县| 昌平区| 津市市| 化德县| 来凤县| 杨浦区| 墨竹工卡县| 安乡县| 清水县| 凤台县| 浦北县|