java 非法提交_Java防止非法和重复表单提交

真是一切都逃不过session,看了DZ的formhash;struts token什么啊,就是个session,安全级别比验证码还低。

看看别人的分析有益身心啊,看之,目前来讲一切都逃不过session

预期达到目标:

1、当用户进行的是Refresh/Reload/Back/Forward操作、以及先Back再Submit操作时,仅仅是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();

}

c、struts(webwork没有找到这个资料)

//验证事务控制令牌,

会自动根据session中标识生成一个隐含input代表令牌,防止两次提交

在action中:

//

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) ...{

// 正常进行操作

}

还可以采用特定的标志来区分,比如

程序里这样判断

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 formhashSession = (Set) session.getAttribute("formhashSession");

if (formhashSession == null) ...{

formhashSession = new HashSet();

}

// 检测重复问题

while (formhashSession.contains(formhash)) ...{

formhash = MD5.encode(Long.toString(new Date().getTime()));

}

// 保存到session里面

formhashSession.add(formhash);

// 保存

session.setAttribute("formhashSession", formhashSession);

表单里面增加如下字段

在表单提交页面进行如下处理

// 拿到表单的formhash

String formhash = upload.getParameter("formhash");

// 拿到session里面的集合

Set formhashSession = (Set) session.getAttribute("formhashSession");

// 如果没有,则是重复提交,或者非法提交

if (formhashSession == null || !formhashSession.contains(formhash)) ...{

out.println("请不要重复提交!");

return;

}

// 下面进行其它的操作

//

// 最后,如果操作成功,从session里面把这个formhash 删掉!

// 以免用户少填写了某个字段,造成表单无法再次提交

formhashSession.remove(formhash);

session.setAttribute("formhashSession", formhashSession);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值