`
jayluns
  • 浏览: 143989 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

利用Session防止表单重复提交

    博客分类:
  • J2EE
阅读更多
为什么需要防止表单重复提交呢?


重复提交不仅仅是验证的问题,有时候可能会出现重复执行业务逻辑。



比如你买东西付款,如果不禁制重复提交,用户心急点两次,或者误操作点两次,

结果扣两次钱,那这个网站还不得立刻死翘翘。
重复提交更多的时候是为了安全来。
-----:
1)包含有Form表单得页面必须通过一个服务器程序动态生成,服务器程序为每次产生得页面中的form表单都分配一个唯一得随机标识号,并在form表单得一个隐藏域 保存

(2)当用户提交form得时候,负责接受这一请求得服务器程序比较form表单隐藏字段中的标识号与存贮在session中的是否相同,当下列情情况时候,服务器程序将忽略提交请求:

      a.当前用户session不存在表单标识
      b.用户提交得表单数据并没有标识号字段
      c.存贮在当前用户的session中得标识号与表单数据中的不同



import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;


public class TokenProcessor {
   private long privious;//上次生成表单标识号得时间值
   private static TokenProcessor instance=new TokenProcessor();
   public static String FORM_TOKEN_KEY="FORM_TOKEN_KEY";
   private TokenProcessor(){
       
   }
   public static TokenProcessor getInstance(){
       return instance;
   }
   /*
    * 验证请求中得标识号是否有效,如果请求中的表单标识与当前用户session中的相同,返回结果true=
    */
   public synchronized boolean isTokenValid(HttpServletRequest request){
       //未避免session对象不存在时候创建Session对象
       HttpSession session=request.getSession(false);
       if(session==null){return false;}
       String saved=(String)session.getAttribute(FORM_TOKEN_KEY);
       if(saved==null){
           return false;
       }
       String token=(String)request.getParameter(FORM_TOKEN_KEY);
       if(token==null){
           return false;
       }
       return saved.equals(token);//直接返回是否和浏览器页面是同一个token
   }
   
   /*
    * 清除存储在当前用户session中的表单标识号
    */
   public synchronized void reset(HttpServletRequest request){
       HttpSession session=request.getSession(false);
       if(session==null){
           return;
       }
       session.removeAttribute(FORM_TOKEN_KEY);
   }
   
   /*
    * 产生表单标识号并将之保存在当前用户得session中
    */
   
   public synchronized void saveToken(HttpServletRequest request){
       HttpSession session=request.getSession();
       try {
        byte id[]=session.getId().getBytes();
        long current=System.currentTimeMillis();
        if(current==privious){
            current++;
        }
        privious=current;
        byte now[]=String.valueOf(current).getBytes();
        MessageDigest md=MessageDigest.getInstance("MD5");
        md.update(id);
        md.update(now);
        String token=toHex(md.digest());
        session.setAttribute(FORM_TOKEN_KEY, token);
      } catch (NoSuchAlgorithmException e) {
        
      }
   }
   /*
    * 将一个字节数转换成十六进制得字符串
    * 
    */
   public String toHex(byte buffer[]){
       StringBuffer sb=new StringBuffer(buffer.length*2);
       for (int i = 0; i < buffer.length; i++) {
        sb.append(Character.forDigit((buffer[i]&0x60)>>4, 16));
        sb.append(Character.forDigit(buffer[i]&0x0f, 16));
    }
       return sb.toString();
       
   }
}




import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class FormDoubleServlet extends HttpServlet {

    //提交的时候访问的servlet
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=gb2312");
        PrintWriter out=response.getWriter();
        TokenProcessor tokemProcessor=TokenProcessor.getInstance();
        if(!tokemProcessor.isTokenValid(request)){
            out.println("重复提交");
        }
        String p1=request.getParameter("p");
        if(p1==null||p1.trim().equals("")){
            out.println("请输入内容");
        }else{
            out.println("提交内容被处理");
            tokemProcessor.reset(request);//清除session中的标识
        }
        
    }
   
} 


<%@ page contentType="text/html; charset=GBK"%>

<%
    TokenProcessor tokemProcessor=TokenProcessor.getInstance();
        tokemProcessor.saveToken(request);
    String token=(String)request.getSession().getAttribute(tokemProcessor.FORM_TOKEN_KEY);
 %>
<html>
    <head>
        <title>用户登陆</title>
    </head>
    <body>
        <form action="/testServlet" method="post">
          <input name="<%=tokemProcessor.FORM_TOKEN_KEY %>" value="<%=token %>">
          <input name="q"/>
          
          <input type="submit" value="submit"/>
        </form>
    </body>
</html>




分享到:
评论

相关推荐

    浅谈利用Session防止表单重复提交

    主要介绍了浅谈利用Session防止表单重复提交,简单介绍表单重复提交的情况,分析,以及解决方法代码示例,具有一定借鉴价值,需要的朋友可以了解下。

    struts2利用token防止表单重复提交(源代码)

    struts2防止表单重复提交,利用struts的拦截器tokenSession,轻轻松松解决表单重复提交的问题。 附件为源代码,后台延迟了3秒,可直接在web服务器下部署运行,输入用户名和密码后,多点几次提交按钮,然后看控制台...

    java实现防止表单重复提交

    服务器端避免表单的重复提交,利用同步令牌来解决重复提交的基本原理如下:(1)用户访问提交数据的页面,服务器端在这次会话中,创建一个session对象,并产生一个令牌值,将这个令牌值作为隐藏输入域的值,随表单一起发送到...

    PHP防止刷新重复提交页面的示例代码

    PHP防止刷新重复提交,通过不断刷新(Refresh or Reload)表单提交页面,可以重复提交表单内容,可以利用 PHP 的 Session 来避免这一点,Session 保存在服务器端,在 PHP 过程中改变 Session 变量的值后,即保存在...

    ASP200问.EXE

    38.如何利用Session防止用户重复投票 40.如何在Session对象失效后重新设置Session对象 41.如何创建、读写和删除Cookie 43.如何遍历Cookies集合 44.如何判断客户端的Cookie是否处于开启状态 45.如何使用Cookie记录...

    PHP程序开发范例宝典III

    实例031 不提交表单获取单选按钮的值 43 实例032 选中单选按钮后显示其他表单元素 44 实例033 根据数据表结构自动生成数据录入页面 45 实例034 投票系统中单选按钮与复选框的应用 47 2.3 下拉列表的应用 ...

    PHP开发实战1200例(第1卷).(清华出版.潘凯华.刘中华).part1

    实例172 不提交表单获取单选按钮的值 207 实例173 实现复选框中的全选、反选和不选 208 实例174 隐藏域提交用户的ID值 210 实例175 图像域替代提交按钮 211 实例176 跳转菜单实现页面跳转 213 实例177 上传图片预览 ...

    PHP开发实战1200例(第1卷).(清华出版.潘凯华.刘中华).part2

    实例172 不提交表单获取单选按钮的值 207 实例173 实现复选框中的全选、反选和不选 208 实例174 隐藏域提交用户的ID值 210 实例175 图像域替代提交按钮 211 实例176 跳转菜单实现页面跳转 213 实例177 上传图片预览 ...

    深入浅出Struts2(附源码)

    第15章防止重复提交 252 15.1 标记管理 252 15.2 使用Token拦截器 253 15.3 使用Token Session拦截器 256 15.4 小结 257 第16章调试与性能分析 258 16.1 debug标签 258 16.2 Debugging拦截器 259 16.3 性能...

    深入浅出Struts 2 .pdf(原书扫描版) part 1

    第15章 防止重复提交 252 15.1 标记管理 252 15.2 使用Token拦截器 253 15.3 使用Token Session拦截器 256 15.4 小结 257 第16章 调试与性能分析 258 16.1 debug标签 258 16.2 Debugging拦截器 259 16.3 性能分析 ...

    asp.net知识库

    SubmitOncePage:解决刷新页面造成的数据重复提交问题 SharpRewriter:javascript + xml技术利用#实现url重定向 采用XHTML和CSS设计可重用可换肤的WEB站点 asp.net的网址重定向方法的比较:面向搜索引擎友好 也谈 ...

    C#编程经验技巧宝典

    8 &lt;br&gt;0018 有效利用Visual Studio 2005附带程序 8 &lt;br&gt;0019 有效使用MSDN帮助 9 &lt;br&gt;0020 如何设置MSDN帮助 9 &lt;br&gt;1.4 其他 10 &lt;br&gt;0021 如何添加项目引用 10 &lt;br&gt;0022 如何添加Web...

Global site tag (gtag.js) - Google Analytics