`

Ajax环境下表单防重复、外部提交实现方案记要

阅读更多

背景:

js lib: Ext 3.3.0,未使用 struts、Spring MVC;

 

所有的表单都由 Ext js 方法生成(即非传统 http form 形式, http 源代码中无 form 元素),后台 http request -> action 的处理机制是和 struts、Spring MVC 的实现相仿。

 

方案核心:

通过 token 机制来防止表单重复或外部提交(非常非常的寻常)。

 

方案实现:

如果用 struts 就简单了,加个<s:token/> 再配个 TokenInterceptor 就搞定了 (存在漏洞,详见底部)。

如果用 Spring MVC 就简单了,写个 TokenHandlerInterceptor extends HandlerInterceptorAdapter 再配置下也搞定了。

 

不用 struts、Spring MVC 其实也简单,参考 Spring MVC 在  http request -> action 的处理中加上拦截器机制,再参考 struts 实现 TokenInterceptor 就搞定了。

 

关于 token 值的提交方式:由于form非常规,无法往 form 里添加 token 元素,既然放不到 request body 里,那就放到 request header 里,放到 header 里其实相对来说更灵活些(另外似乎还能避免1个漏洞,详见底部)。

 

Ext request 加 header :

 

Ext.Ajax.defaultHeaders = {
    'Req-Token': tokenValue
};

注:header 的名称是不区分大小写的,根据实际测试情况,IE下通常会把 header 名称都变成小写,而 Firefox 和 Chrome 基本上不会改变,header 名称和我们代码里所写的名称是一致的。后台获取 header 值时需注意这个情况。

 

同样的,response 里也加个 header,将新的 token 值传给客户端。

不专门提供一个获取 token 值的 servlet 的原因:主要是怕该 servlet 压力过大。

 

另外,不能将 token值的提交和form提交分开,必须在同一个请求中同时提交,原因:分开提交无法防止外部提交等非法提交方式。

 

关于是否需要进行 token 校验:由于 TokenInterceptor 配上了,则默认会对所有 request 均校验,为了支持按需进行校验,自定义了@Token 注解,需要校验的action方法只要加上 @Token 即可(注解是个好东西)。

 

特别注意:

CSRF

CSRF攻击原理解析

Struts2 csrf token绕过漏洞

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics