反复递交、反复更新、避免后退的难题和解决方

日期:2021-03-22 类型:科技新闻 

关键词:如何制作微信小游戏,微信游戏小程序,公众号游戏,h5小游戏模板,小程序游戏源码

1。序言
你在任何1个较为技术专业的BBS都会看到这样的难题,即便你Google1下,也会发现有许多的人在关心和了解,但大伙儿得出的处理方式却全是千差万别,(有的人认为选用脚本制作来处理;有的则想重定项到其他网页页面;有的则将此难题提高到Token的角度)为何会有这般大的差别呢?
2。难题情景
最先,大家应当先掌握为何要解决这样的难题?或技术专业1点便是它合适的情景是甚么?(好像仅有人来问沒有人来解释)
1。反复递交、反复更新的情景
反复递交、反复更新全是来处理系统软件反复纪录的难题。也便是说某本人在数次的递交某条纪录(为何?或许是闲了沒有事儿干的;最有将会是客户压根就不知道道自身的递交結果是不是早已实行了?!)。
但出現了这样的难题其实不见得就务必解决,要看你所开发设计的系统软件的种别而定。例如你接手的是某个資源管理方法系统软件,系统软件自身从要求的角度压根就不容许出現"反复"的纪录,在这样要求的管束标准下,去实行反复的递交姿势只会引起“业务流程级出现异常”的造成,压根就不能能实行取得成功也就没有谓防止不防止的难题了。
2。避免后退的情景
掌握了反复更新、反复递交的情景,大家来掌握1下"避免后退"实际操作的缘故是甚么?例如你在开发设计某个网络投票系统软件,它有许多的流程,而且这些流程之间是有联络的,例如第1步会将一些信息内容推送给第2步,第2步缓存文件了这些信息内容,另外将本身的信息内容推送给了第3步。。。。。这些,假如此时客户处在第3流程下,大家想像1下某个顽皮客户的客户点一下了后退按钮,此时显示屏出現了第2流程的网页页面,他再度的改动或再度的递交,进到到下1个流程(也便是第3流程),不正确就会在此造成?!甚么不正确呢?最为典型的便是这样的实际操作立即致使了针对第1个流程信息内容的遗失!(假如这样的信息内容是借助Request储放的话,自然你能够储放在Session或更大的左右文自然环境中,但这并不是个好主张!有关信息内容储放的难题,下一次在就这个难题详尽的探讨)
3。怎样解决的难题
自然许多的系统软件(例如订票系统软件从要求上自身是容许本人反复订票的)是务必要防止反复更新、反复递交、和避免后退的难题的,但即便是这样的难题,也要区别怎样解决和在哪儿里解决的(在网上只是告知你怎样解决,但非常少去区别在哪儿里解决的),明显解决的方法不过是顾客端或服务器端两种,而应对不一样的部位解决的方法也是不一样的,但有1点要事前申明:任何顾客端(特别是B/S端)的解决全是不能信赖的,最好是的也是最应当的是服务器端解决方式。
顾客端解决:
应对顾客端大家可使用Javascript脚本制作来处理,以下
1。反复更新、反复递交
Ways One:设定1个自变量,只容许递交1次。

拷贝编码
编码以下:

<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更换当今的历史时间记录,这样访问历史时间纪录中就仅有1个网页页面,后退按钮始终不容易变成能用。”例如应用javascript:location.replace(this.href); event.returnValue=false;

2.服务器端解决(这里只说Struts架构的解决)
运用同歩令牌(Token)体制来处理Web运用中反复递交的难题,Struts也得出了1个参照完成。
基础基本原理:
服务器端在解决抵达的恳求以前,会将恳求中包括的令牌值与储存在当今客户对话中的令牌值开展较为,
看是不是配对。在解决完该恳求后,且在回应推送给顾客端以前,可能造成1个新的令牌,该令牌除发送给
顾客端之外,也会将客户对话中储存的旧的令牌开展更换。这样假如客户返回到刚刚的递交网页页面并再度
递交的话,顾客端传过来的令牌就和服务器端令牌不1致,从而合理地避免了反复递交的产生。
if (isTokenValid(request, true)) {
// your code here
return mapping.findForward("success");
} else {
saveToken(request);
return mapping.findForward("submitagain");
}
Struts依据客户对话ID和当今系统软件時间来转化成1个唯1(针对每一个对话)令牌的,实际完成能够参照
TokenProcessor类中的generateToken()方式。
1. //认证事务管理操纵令牌,<html:form >会全自动依据session中标志转化成1个暗含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有这样的1个方式转化成令牌
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);
}
}
总结
针对反复递交、反复更新、避免后退这些全是属于系统软件为防止反复纪录而必须处理的难题,在顾客端好去处理必须对于每种的将会提出相应的处理计划方案,但是在服务器端来看只但是是针对数据信息真正性的检测难题,根据令牌的解决便是1劳永逸的方式。
另外大家也看到,从不一样的角度去看待难题,其处理的方式也是不一样的。顾客端更追求完美的是客户的实际操作,而服务端则将留意力放在了数据信息的解决上,因此在某个针对服务器端看似非常容易的难题上,用顾客端来处理却不便了许多!反之仍然。因此在一些难题的解决上大家必须综合性考虑到友谊衡,是用顾客端来处理?還是用服务器端来解决?
 
网页页面防更新反复递交、防后退处理方式
递交后禁用递交按钮(绝大多数人全是这样做的)
假如顾客递交后,按F5更新如何办?
应用Session
在递交的网页页面也便是数据信息库解决以前:
if session("ok")=true then
response.write "不正确,正在递交"
response.end
end if
数据信息解决完后,改动session("ok")=false。
数据信息解决取得成功立刻Redirect到此外1个网页页面
实际操作后更新确实是个难题,你可使用自动跳转网页页面、关掉本网页页面,假如是有主要参数据标准来操纵的,那就应当好做了,能够立即改动window.location的值,把主要参数所有改掉,这样就类似了。
缺陷:简易地应用Response.Redirect将已不合理,由于客户从1个网页页面转到另外一个网页页面,大家都务必用顾客端编码消除location.history。留意,这类方式消除的是最终1个浏览历史时间纪录,而并不是所有的浏览纪录。点一下后退按钮,再点一下后退按钮,你能够看到这时候开启的是本网页页面以前的网页页面!(自然,这是在你的顾客端开启了JavaScript作用的标准下。)
假如顾客按后退,如何办?

避免网页页面后退--严禁缓存文件
大家在开展数据信息库加上实际操作的情况下,假如容许后退,而恰巧有更新了网页页面,就会再度实行加上实际操作,无疑这并不是大家必须的,像1般在网上许多严禁缓存文件的编码,有时其实不靠谱,这时候你要是在实际操作的网页页面再加便可以了,在网页页面的里特定要定项的新页,再点后退,看是否不容易再退到刚刚的实际操作网页页面了,具体上早已把这个历史时间给删掉了
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(⑴);
Response.Expires=0;
Response.CacheControl="no-cache";
到底如何才可以"禁用"访问器的后退按钮?或“如何才可以避免客户点一下后退按钮回到之前访问过的网页页面?”
遗憾的是,大家没法禁用访问器的后退按钮。
避免网页页面后退--新开对话框
用window.open弹出表单网页页面,点递交后关掉该页;解决递交的ASP页也是用弹出,设置表单的target,点递交时window.open("XXX.asp","_blank"),随后用JS来递交表单,进行后window.close();
简易的说,便是递交表单的情况下弹出新对话框,关掉本对话框。针对window.open()开启的对话框如何后退?能后退到哪里去?
呵呵,罗嗦了1堆空话,了解如何解决了么?混和应用顾客端脚本制作和服务器端脚本制作。
 
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
转化成1个令牌储存在客户session中,在form中加1个hidden域,显示信息该令
牌的值,form递交后再次转化成1个新的令牌,将客户递交的令牌和session
中的令牌较为,如同样则是反复递交
3
在你的服务器端控制的编码中应用Response.Redirect("selfPage")句子。可是大多数的数都不应用这类方式。
方式也有许多。。。
4
<input type="button" value="递交" onclick="this.disabled=true;this.form.submit()">
5
在JSP网页页面的FORM表单中加上1个hidden域
<input type="hidden" name="url"value=<%=request. getRequestURL_r()%>>

在你的serverlet中加上以下句子
String url=request. getParameter_r("url");
response.sendRedirect(url);
我1般全是选用这样的方式回到JSP网页页面的,不太搞清楚你说的反复更新是甚么定义
6 ajax 无更新递交
7 Web开发设计中避免访问器的更新键引发系统软件实际操作反复递交
如何处理呢?重定项能够处理网页页面更新带来的数据信息的反复递交的难题,大家当然能够运用重定项的方法来处理这个难题。可是struts的action里边mapping.findword();自动跳转的话,默认设置的是在工程项目文档夹里边找要自动跳转的网页页面。这类状况,如何处理呢?
改动struts-config.xml 文档,在action里边有1个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>

访问器有关难解决的难题
访问器的后退按钮使得大家可以便捷地回到之前浏览过的网页页面,它无疑十分有效。但有时大家迫不得已关掉这个作用,防止止客户打乱预订的网页页面浏览顺序。本文详细介绍互联网上可寻找的各种各样禁用访问器后退按钮计划方案,剖析它们各有的优缺陷和可用场所。
1、简述

   以前有很多人问起,“如何才可以‘禁用’访问器的后退按钮?”,或“如何才可以避免客户点一下后退按钮回到之前访问过的网页页面?”在ASP论坛上,这个难题也是问得数最多的难题之1。遗憾的是,回答十分简易:大家没法禁用访问器的后退按钮。
   先是我针对竟然有人要想禁用访问器的后退按钮觉得不能思议。后来,看到居然有那末多的人要想禁用这个后退按钮,我也就释怀(要想禁用的仅有后退按钮,不包含访问器的前行按钮)。由于在默认设置状况下,客户递交表单以后能够根据后退按钮回到表单网页页面(而并不是应用“编写”按钮!),随后再度编写并递交表单边数据信息库插进新的纪录。这是大家不肯看到的。
   因而我就决策要找出防止出現这类状况的方式。我浏览了很多网站,参照了这些网站所详细介绍的各种各样完成方式。假如你常常浏览ASP程序编写网站,本文所详细介绍的一部分內容你将会早已见到过。本文的每日任务是把各种各样将会的方式都详细介绍给大伙儿,随后找出最好是的方式!
2、严禁缓存文件
   在我寻找的很多计划方案中,在其中有1种提议严禁网页页面缓存文件。实际是应用服务器端脚本制作,以下所示:
<%
Response.Buffer = True
Response.ExpiresAbsolute = Now() - 1
Response.Expires = 0
Response.CacheControl = "no-cache"
%>
   这类方式十分合理!它强制性访问赏识新浏览服务器免费下载网页页面,而并不是从缓存文件载入网页页面。应用这类方式时,程序编写者的关键每日任务是建立1个对话级的自变量,根据这个自变量明确客户是不是依然能够查询那个不合适根据后退按钮浏览的网页页面。因为访问器已不缓存文件这个网页页面,当客户点一下后退按钮时访问器将再次免费下载该网页页面,此时程序流程便可以查验那个对话自变量,看看是不是应当容许客户开启这个网页页面。

   比如,假定大家有以下表单:

<%
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查验客户是不是是第1次浏览当今网页页面。假如并不是第1次(即Session("FirstTimeToPage")包括某个值),那末大家就消除对话自变量的值,随后把客户再次定项到1个刚开始网页页面。这样,当表单递交时(此时SompePage.asp挨打开),大家务必授予FirstTimeToPage1个值。即,在SomePage.asp中大家必须再加下面的编码:
Session("FirstTimeToPage") = "NO"
   这样,早已开启SomePage.asp的客户假如点一下后退按钮,访问器将再次恳求服务器免费下载网页页面,服务器查验到Session("FirstTimeToPage")包括了1个值,因而就消除Session("FirstTimeToPage"),并把客户重定项到别的网页页面。自然,全部这1切都必须客户开启了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: ⑴”同样,此时访问器依然缓存文件网页页面,但把网页页面标识为马上到期。在IE 4或5中,“Cache-Control”META HTTP-EQUIV标识将被忽视,不起功效。
   在具体运用中大家能够再加全部这些编码。但是,因为这类方式不可以可用于全部的访问器,因此是不强烈推荐应用的。但假如是在Intranet自然环境下,管理方法员能够操纵客户应用哪样访问器,我想還是有人会应用这类方式。
3、别的方式

   接下来大家要探讨的方式之后退按钮自身为管理中心,而并不是访问器缓存文件。这儿有1篇文章内容Rewiring the Back Button很值得参照。但是我留意到,假如应用这类方式,尽管客户点一下1下后退按钮时他不容易看到之前键入数据信息的网页页面,但要是点一下两次便可以,这可并不是大家期待的实际效果,由于许多情况下,固执己见的客户一直可以寻找绕开防止对策的方法。
   此外1种禁用后退按钮的方法是用顾客端JavaScript开启1个沒有专用工具条的对话框,这使得客户很难回到前1网页页面,但并不是不能能。1种更安全性但非常恼人的方式是,当表单递交时开启1个新的对话框,与此另外关掉表单所属的对话框。但我感觉这类方式不值得得用心考虑到,由于大家总不可以让客户每递交1个表单就开启1个新对话框。
   那末,在那个大家不想让客户回到的网页页面是不是还可以添加JavaScript编码呢?在这个网页页面中添加的JavaScript编码能用来造成点一下前行按钮的实际效果,这样也就相抵了客户点一下后退按钮所造成的姿势。用于完成该作用的JavaScript编码以下

所示:
<script language="JavaScript">
<!--
javascript:window.history.forward(1);
//-->
</script>
   一样地,这类方式尽管合理,但间距“最好是的方式”还差得很远。后来我又看到有人提议用location.replace从1个网页页面转到另外一个网页页面。这类方式的基本原理是,用新网页页面的URL更换当今的历史时间记录,这样访问历史时间纪录中就仅有1个网页页面,后退按钮始终不容易变成能用。我想这将会更是很多人所寻找的方式,但这类方式依然并不是任何状况下的最好是方式。应用这类方式的案例以下所示:
<A HREF="PageName.htm" onclick="javascript:location.replace(this.href);
event.returnValue=false;">严禁后退到本网页页面的连接</A>
   严禁后退到本网页页面的连接!
   这类方式的缺陷在于:简易地应用Response.Redirect将已不合理,这是由于每次客户从1个网页页面转到另外一个网页页面,大家都务必用顾客端编码消除location.history。此外还要留意,这类方式消除的是最终1个浏览历史时间纪录,而并不是所有的浏览纪录。
   点一下上面的连接,你将开启1个简易的HTML网页页面。再点一下后退按钮,你能够看到这时候开启的并不是本网页页面,而是本网页页面以前的网页页面!(自然,你务必在访问器中开启了顾客端JavaScript编码。)
   历经1番细心的寻追寻觅以后,我发现依然没法找出真实可以彻底禁用访问器后退按钮的方法。全部这里详细介绍的方式都可以在不一样水平上、以不一样的方法严禁客户回到前1网页页面,但它们都有各有的局限。因为不存在可以彻底禁用后退按钮的方式,因此最好是的计划方案应当是:混和应用顾客端脚本制作和服务器端脚本制作。

<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、一般应当在业务流程层开展分辨(唯1性)处理这类难题
2、要在网页页面装载恶性事件写上 Response.CacheControl = "no-cache" 消除缓存文件
3、也是有人这样说:我之前也碰到过这样的难题,是在分步递交中1本人的简历,在写完第1个网页页面后跳到第2个网页页面,以便避免客户用后退回到到第1个网页页面,再再次递交第1个网页页面,我是当客户递交第1次递交第1个网页页面时,把插进数据信息库中的纪录的自提高id号放到session里,当客户从第2个网页页面回到到第1个网页页面再1次递交该网页页面时,我就用session里的值去数据信息库查,假如有这个id就用update句子把第1个网页页面的数据信息写进数据信息库,假如沒有查到这个id,就用insert句子。