JavaWeb中HttpSession中表单的重复提交示例
表单的重复提交
- 重复提交的情况:
①.在表单提交到一个Servlet,而Servlet又通过请求转发的方式响应了一个JSP(HTML)页面,此时地址栏还保留着Servlet的那个路径,在响应页面点击“刷新”。
②.在响应页面没有到达时,重复点击“提交按钮”
③.点击返回,再点击提交
- 不是重复提交的情况:点击“返回”,“刷新”原表单页面,再点击提交。
- 如何避免表单的重复提交:在表单中做一个标记,提交到Servlet时,检查标记是否存在且和预定义的标记一样,若一致,则受理请求,并销毁标记,若不一致或没有标记,则直接响应提示信息:“重复提交”
①仅提供一个隐藏域不行:<inputtype="hidden"name="token"value="lsy">
②把标记放在Request中,行不通,表单页面刷新后,request已经被销毁,再提交表单是一个新的request的。
③把标记放在Session中,可以
1.在原表单页面,生成一个随机值token
2.在原表单页面,把token值放入session属性中
3.在原表单页面,把token值放入到隐藏域
4.在目标的Servlet中:获取session和隐藏域中的token值
比较两个值是否一致,受理请求,且把session域中的token属性清除,若不一致,则直接响应提示页面:“重复提交”
我们可以通过Struts1中写好的类TokenProcessor来重构代码,面向组件编程
packagecom.lsy.javaweb;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpSession;
importjava.security.MessageDigest;
importjava.security.NoSuchAlgorithmException;
publicclassTokenProcessor{
privatestaticfinalStringTOKEN_KEY="TOKEN_KEY";
privatestaticfinalStringTRANSACTION_TOKEN_KEY="TRANSACTION_TOKEN_KEY";
/**
*Thesingletoninstanceofthisclass.
*/
privatestaticTokenProcessorinstance=newTokenProcessor();
/**
*Thetimestampusedmostrecentlytogenerateatokenvalue.
*/
privatelongprevious;
/**
*ProtectedconstructorforTokenProcessor.Use
*TokenProcessor.getInstance()toobtainareferencetotheprocessor.
*/
protectedTokenProcessor(){
super();
}
/**
*Retrievesthesingletoninstanceofthisclass.
*/
publicstaticTokenProcessorgetInstance(){
returninstance;
}
/**
*<p>
*Return<code>true</code>ifthereisatransactiontokenstoredinthe
*user'scurrentsession,andthevaluesubmittedasarequestparameter
*withthisactionmatchesit.Returns<code>false</code>underanyofthe
*followingcircumstances:
*</p>
*
*<ul>
*
*<li>Nosessionassociatedwiththisrequest</li>
*
*<li>Notransactiontokensavedinthesession</li>
*
*<li>Notransactiontokenincludedasarequestparameter</li>
*
*<li>Theincludedtransactiontokenvaluedoesnotmatchthetransaction
*tokenintheuser'ssession</li>
*
*</ul>
*
*@paramrequest
*Theservletrequestweareprocessing
*/
publicsynchronizedbooleanisTokenValid(HttpServletRequestrequest){
returnthis.isTokenValid(request,false);
}
/**
*Return<code>true</code>ifthereisatransactiontokenstoredinthe
*user'scurrentsession,andthevaluesubmittedasarequestparameter
*withthisactionmatchesit.Returns<code>false</code>
*
*<ul>
*
*<li>Nosessionassociatedwiththisrequest</li>
*<li>Notransactiontokensavedinthesession</li>
*
*<li>Notransactiontokenincludedasarequestparameter</li>
*
*<li>Theincludedtransactiontokenvaluedoesnotmatchthetransaction
*tokenintheuser'ssession</li>
*
*</ul>
*
*@paramrequest
*Theservletrequestweareprocessing
*@paramreset
*Shouldweresetthetokenaftercheckingit?
*/
publicsynchronizedbooleanisTokenValid(HttpServletRequestrequest,booleanreset){
//Retrievethecurrentsessionforthisrequest
HttpSessionsession=request.getSession(false);
if(session==null){
returnfalse;
}
//Retrievethetransactiontokenfromthissession,and
//resetitifrequested
Stringsaved=(String)session.getAttribute(TRANSACTION_TOKEN_KEY);
if(saved==null){
returnfalse;
}
if(reset){
this.resetToken(request);
}
//Retrievethetransactiontokenincludedinthisrequest
Stringtoken=request.getParameter(TOKEN_KEY);
if(token==null){
returnfalse;
}
returnsaved.equals(token);
}
/**
*Resetthesavedtransactiontokenintheuser'ssession.Thisindicates
*thattransactionaltokencheckingwillnotbeneededonthenextrequest
*thatissubmitted.
*
*@paramrequest
*Theservletrequestweareprocessing
*/
publicsynchronizedvoidresetToken(HttpServletRequestrequest){
HttpSessionsession=request.getSession(false);
if(session==null){
return;
}
session.removeAttribute(TRANSACTION_TOKEN_KEY);
}
/**
*Saveanewtransactiontokenintheuser'scurrentsession,creatinga
*newsessionifnecessary.
*
*@paramrequest
*Theservletrequestweareprocessing
*/
publicsynchronizedStringsaveToken(HttpServletRequestrequest){
HttpSessionsession=request.getSession();
Stringtoken=generateToken(request);
if(token!=null){
session.setAttribute(TRANSACTION_TOKEN_KEY,token);
}
returntoken;
}
/**
*Generateanewtransactiontoken,tobeusedforenforcingasingle
*requestforaparticulartransaction.
*
*@paramrequest
*Therequestweareprocessing
*/
publicsynchronizedStringgenerateToken(HttpServletRequestrequest){
HttpSessionsession=request.getSession();
returngenerateToken(session.getId());
}
/**
*Generateanewtransactiontoken,tobeusedforenforcingasingle
*requestforaparticulartransaction.
*
*@paramid
*auniqueIdentifierforthesessionorothercontextinwhich
*thistokenistobeused.
*/
publicsynchronizedStringgenerateToken(Stringid){
try{
longcurrent=System.currentTimeMillis();
if(current==previous){
current++;
}
previous=current;
byte[]now=newLong(current).toString().getBytes();
MessageDigestmd=MessageDigest.getInstance("MD5");
md.update(id.getBytes());
md.update(now);
returntoHex(md.digest());
}catch(NoSuchAlgorithmExceptione){
returnnull;
}
}
/**
*ConvertabytearraytoaStringofhexadecimaldigitsandreturnit.
*
*@parambuffer
*Thebytearraytobeconverted
*/
privateStringtoHex(byte[]buffer){
StringBuffersb=newStringBuffer(buffer.length*2);
for(inti=0;i<buffer.length;i++){
sb.append(Character.forDigit((buffer[i]&0xf0)>>4,16));
sb.append(Character.forDigit(buffer[i]&0x0f,16));
}
returnsb.toString();
}
}
以上所述是小编给大家介绍的JavaWeb中HttpSession中表单的重复提交示例,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!