`
todd_liu
  • 浏览: 66084 次
  • 性别: Icon_minigender_1
  • 来自: 江苏
社区版块
存档分类
最新评论

Java防止非法和重复表单提交

阅读更多

真是一切都逃不过session,看了DZ的formhash;struts token什么啊,就是个session,安全级别比验证码还低。
看看别人的分析有益身心啊,看之,目前来讲一切都逃不过session


预期达到目标
:

       1、当用户进行的是Refresh/Reload/Back/Forward操作、以及先BackSubmit操作时,仅仅是reloading先前的结果页。

       2、当用户重复提交同一个任务操作时,后台服务接收并处理第一次提交的任务,后面提交不起作用(不转向也不提示)。

       3、该功能具有公用性。

基本形成思路:

       1、在basic filter中实现公用性

                if(true){//问题1:如何确定是否为重复提交

                         ...

                         chain.doFilter(request,response);

                }else{

                         //问题2:如何实现不转向、不提示也不显示空白页

                }

       2、网上资料概括

                a、提交表单后按钮变灰/隐藏提交按钮

                b、在js里设置全局变量,提交后修改该变量的值,依据变量的值判断是否重复提交

                         var flag=true;

                         function checkForm(){

                                   if (flag==false){

                                            return;

                                   }

                        

                                   flag=false;

                                   document.form1.submit();

                        

                         }

                cstruts webwork没有找到这个资料)

                         //验证事务控制令牌,<html:form >会自动根据session中标识生成一个隐含input代表令牌,防止两次提交

                         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中的令牌

                        

                         action有这样的一个方法生成令牌华

                            protected String generateToken(HttpServletRequest request) {

                        

                                HttpSession session = request.getSession();

                                try {

                                    byte id[] = session.getId().getBytes();

                                    byte now[] =

                                        new Long(System.currentTimeMillis()).toString().getBytes();

                                    MessageDigest md = MessageDigest.getInstance("MD5");

                                    md.update(id);

                                    md.update(now);

                                    return (toHex(md.digest()));

                                } catch (IllegalStateException e) {

                                    return (null);

                                } catch (NoSuchAlgorithmException e) {

                                    return (null);

                                }

                        

                            }          

                d、用户使用浏览器时,可以经常使用向后的按钮,因此就有可能重复提交一个他们已经提交过的form,这样就会带来一个重复事务处理的问题。同样,一个用户也可能在接收到一个确认的页面之前按下停止的按钮,接着再次提交同一个form。对于这些情况,我们都想跟踪并且禁止这些重复的提交,我们可以使用一个控制servlet来提供一个控制点,以解决这个问题。

                  同步记号(Synchronizer (or Dvu) Token

               

这个策略是为了解决重复的form提交问题。一个同步的记号被设置在一个用户的Session中,并且包含在返回到客户的每一个form中。当form被提交时,form中的同步标记就和Session中的同步标记作对比。在form首次提交的时候,这两个标记应该是一样的。如果标记不一样,那么该form就会禁止提交,一个错误就会返回给用户。在用户提交一个form时,如果按下浏览器中的后退按钮并尝试重新提交同一个form时,标记就会出现不匹配的现象。

另一方面,如果两个标记值匹配,那么我们就可以确信整个流程是正确的。在这种情况下,Session中的标记值就会被修改为一个新的值,同时允许提交该form。                                   你也可以使用这个策略来控制对某些页面的直接访问,就好象上面资源保护中描述的一样。例如,假设一个用户将某个应用的页面A收藏到收藏夹中,而页面A只允许通过页面B和C访问。当用户直接通过收藏夹来访问页面A,这时页面的访问顺序就是不正确的,这样同步标记将处在一个不同步的状态,或者它根本就不存在。不论怎样,访问都被禁止了。                 e、做一个hidden框,名字自己定,提交后得到这个值放入session,提交前判断session是否为空   解决方案:        1、后台公共类中实现前台的Form中自动生成两个hidden文本功能,一个是作page是否重复提交判断,并由系统自动附上关键值(如struts采用的方案);另一个作为button是否重复提交判断(struts中好像没有)。由后台公共类实现界面两个hidden text自动生成的好处在于公用性。        2、在basic filter中根据两个hidden text值判断是否为重复提交。        3、javascript中作一个公共方法,实现功能:如果需要判断是否重复提交,就给第二个hidden text附上关键值,并使该功能不可用。 . 个人感想:我相信未来该功能一定会被服务器集成,而不再由开发人员进行编码.

----------------------------------------示例代码----------------------------------------------------

第一,对于不支持POST的,可以简单的使用如下代码
if ("POST".equals(request.getMethod())) ...{
  // 正常进行
}else...{
  // 异常请求
  out.print("异常访问");
  return;
}
如果是servlet, 可以将doGet方法直接返回,不进行处理就行了
public void doGet(HttpServletRequest request, HttpServletResponse response) ...{
  return;
}
public void doPost(HttpServletRequest request, HttpServletResponse response) ...{
  // 正常进行操作
}
还可以采用特定的标志来区分,比如
<form><input type="hidden" name="action" value="insert"/></form>
程序里这样判断
if ("POST".equals(request.getMethod()) && ("insert".equals(request.getParameter("action")))) ...{
  // 正常进行
}else...{
  // 异常请求
  out.print("异常访问");
  return;
}
第二,判断提交的来源referer,代码如下
if ("POST".equals(request.getMethod())) ...{
  String referer = request.getHeader("referer");
  if (referer == null || !referer.startsWith("http://"+request.getServerName())) ...{
    // 非法来源
    return;
  }
  // 正常进行
}else...{
  // 异常请求
  out.print("异常访问");
  return;
}
第三 防止重复提交的hashCode
在表单显示页面
  //生成一个formhash,算法可以自己定,不随便重复就可以了
  String formhash = MD5.encode(Long.toString(new Date().getTime()));
  //读取当前session里面的hashCode集合,此处使用了Set,方便判断。
  Set<String> formhashSession = (Set<String>) session.getAttribute("formhashSession");
  if (formhashSession == null) ...{
    formhashSession = new HashSet<String>();
  }
  // 检测重复问题
  while (formhashSession.contains(formhash)) ...{
    formhash = MD5.encode(Long.toString(new Date().getTime()));
  }
  // 保存到session里面
  formhashSession.add(formhash);
  // 保存
  session.setAttribute("formhashSession", formhashSession);
表单里面增加如下字段
<input type="hidden" name="formhash" id="formhash" value="<%=formhash%>" />
在表单提交页面进行如下处理
    // 拿到表单的formhash
    String formhash = upload.getParameter("formhash");
    // 拿到session里面的集合
    Set<String> formhashSession = (Set<String>) session.getAttribute("formhashSession");
    // 如果没有,则是重复提交,或者非法提交
    if (formhashSession == null || !formhashSession.contains(formhash)) ...{
      out.println("请不要重复提交!");
      return;
    }
    // 下面进行其它的操作
    //
    // 最后,如果操作成功,从session里面把这个formhash 删掉!
    // 以免用户少填写了某个字段,造成表单无法再次提交
    formhashSession.remove(formhash);
    session.setAttribute("formhashSession", formhashSession);

分享到:
评论

相关推荐

    Java表单重复提交的避免方法

    Java表单重复提交是Web开发中常见的问题,可能导致数据不一致和系统异常。要理解这个问题,首先要明白表单提交的基本流程:用户打开表单页面,填写信息,然后点击提交按钮,浏览器向服务器发送请求,服务器处理请求...

    防止页面的重复提交和刷新

    ### 防止页面的重复提交和刷新 #### 一、引言 在现代Web应用开发过程中,确保数据完整性与用户体验至关重要。其中,“防止页面的重复提交和刷新”这一问题尤为关键,它不仅关系到系统的稳定性,还直接影响用户体验...

    防重复提交代码

    2. **Token验证**:当接收到表单提交请求时,先检查Token是否有效。 ```java if (!this.isTokenValid(request) && (int) state &gt; 0) { this.saveToken(request); } else { // 处理业务逻辑 session....

    Struts解决重复提交步骤

    1. **在表单提交前生成令牌**: ```java saveToken(request); ``` 2. **在提交表单的方法中验证令牌**: ```java if(!isTokenValid(request)){ ActionMessages errors = new ActionMessages(); errors.add(...

    一种Java Web数据提交中的防刷新令牌.pdf

    Java Web 应用系统中,通过表单提交数据是一种非常普遍的操作处理方式。然而,用户无意或有意地刷新页面容易导致数据的重复提交,影响数据的完整性、一致性。本文分析了现有的处理方式的不足,讨论了如何通过基于...

    struts的令牌机制,防止重复提交

    1. **使用统一的方法**:为所有涉及表单提交的Action创建统一的方法来处理令牌的生成和验证。 2. **错误处理**:对于验证失败的情况,应该给出明确的错误提示,告知用户发生了什么问题。 3. **避免使用GET方式提交**...

    Java实训教程 Java软件开发实战 Java开发框架介绍 struts2_表单校验失败跳input视图问题共13页.pptx

    在Web应用开发中,表单校验是非常重要的环节之一,能够有效防止非法数据的提交,提高系统的安全性与稳定性。Struts2提供了一套完整的表单校验机制,包括但不限于客户端验证、服务器端验证以及自定义验证规则等。 ##...

    struts2token回退刷新

    如果不匹配或者令牌不存在,那么表单提交将被拒绝,以此来防止重复提交或非法请求。 4. **令牌回退**:当表单提交成功后,为了防止用户意外刷新页面导致重复提交,Struts2会清除服务器会话中的令牌。这种行为称为...

    Java实现验证码验证功能

    在IT行业中,验证码验证功能是网站和应用程序安全的重要组成部分,它可以防止恶意自动化脚本或机器人进行非法操作。本文将深入探讨如何使用Java编程语言来实现验证码验证,主要涉及Servlet、session以及画板对象等...

    java工具类——验证码(VerifyCode)

    - 为了防止重复刷新导致验证码改变,可以使用`session`对象存储当前的验证码内容,同时在客户端通过JavaScript获取图片的`src`,并在表单提交时一并发送验证码值。 4. **验证过程** - 客户端输入验证码后,将其值...

    java web考试报名系统

    系统可能利用jQuery进行表单提交和数据验证,确保信息完整且符合规范。同时,系统通过邮箱验证机制来增加安全性,防止恶意注册或误操作。这里会用到邮件注册的功能,系统向考生提供的邮箱发送一封包含UUID(无重复的...

    kindeditor 上传图片java

    - 将接收到的二进制数据保存为图片文件,可能需要对文件名进行处理,避免重复或非法字符。 - 记录上传信息,如文件名、上传时间、文件大小等。 - 返回一个JSON或HTML响应,告知前端上传结果,包括成功或失败信息...

    爬虫javaDemo

    1. **网页登录**:有些网站需要登录才能访问,Java爬虫需要模拟登录过程,可能涉及POST提交表单、处理验证码等。 2. **动态加载内容**:现代网页常使用AJAX技术,部分内容动态加载,需使用Selenium、Puppeteer等...

    经典表单验证.rar

    在IT领域,表单验证是Web开发中的一个关键环节,其主要目的是确保用户提交的数据有效、完整且符合预设的规则,从而维护数据的完整性和准确性。"经典表单验证.rar"这个压缩包文件,根据其标题和描述,很可能是包含了...

    java写的简单蜘蛛程序

    - POST请求:当需要提交表单数据时,如登录网站,会使用POST请求。 4. **多线程**: - 为了提高爬虫效率,通常会使用多线程并发抓取不同网页,但要注意控制并发量,避免对目标网站造成过大压力。 5. **爬虫策略*...

    Java EE--注册登录系统

    在本系统中,JSP用于展示注册和登录表单,以及处理表单提交后的结果展示。 4. **MD5加密**:MD5(Message-Digest Algorithm 5)是一种广泛使用的哈希函数,可以将任意长度的数据转化为固定长度的摘要。在用户注册时...

    Java 验证码制作

    同时,表单提交时会携带用户的验证码输入,以便于Servlet进行验证。 总结,Java验证码制作涉及了字符串生成、图像处理以及服务器与客户端的交互等多个环节。通过学习以上步骤,开发者可以更好地理解验证码的实现...

    jsp验证码提交实现

    1. 表单提交:创建一个包含验证码输入框的表单,用户需要输入看到的验证码。 ```html 提交"&gt; ``` 2. 验证码验证:在`SubmitServlet`中,获取用户输入的验证码并与session中的验证码进行比较。 ```java ...

    java汉字验证码

    Java汉字验证码是一种用于验证用户身份的安全机制,常用于防止恶意自动化程序(如机器人)进行非法操作,例如注册、登录或提交表单。在本话题中,我们将深入探讨如何使用Java来实现汉字验证码的生成和验证。 1. **...

    java_jsp_网上投票系统

    - 表单提交:用户选择投票选项后,通过POST请求将数据提交到服务器。 7. **安全性考虑**: - 防止SQL注入:使用预编译语句或参数化查询来避免恶意输入影响数据库。 - 用户验证:可能有登录系统以防止重复投票或...

Global site tag (gtag.js) - Google Analytics