Token注解防止表单的重复提交
注解的一些基础:
参见http://blog.csdn.net/duo2005duo/article/details/50505884和
http://blog.csdn.net/duo2005duo/article/details/50511476这两篇文章
1,自定义一个注解@Token 用来标记需要防止重复提交的方法
package com.bjca.framework.util;
/**
* <p>
*关于这个方法的用法是:
*在需要生成token的controller上增加@Token(save=true),
*而在需要检查重复提交的controller上添加@Token(remove=true)就可以了
*另外,你需要在view里在form里增加下面代码:
*<input type="hidden" name="token" value="${token}">
* 此时会在拦截器中验证是否重复提交
* </p>
*
*/
import java.lang.annotation.*; @Target(ElementType.METHOD)
@Retention (RetentionPolicy.RUNTIME)
public @interface Token { boolean save() default false ; boolean remove() default false ;
}
2,自定义一个针对该注解的拦截器 TokenInterceptor
package com.bjca.framework.util; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.UUID; public class TokenInterceptor extends HandlerInterceptorAdapter {
public static Log log = LogFactory.getLog(TokenInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(handler.getClass());
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
Token annotation = method.getAnnotation(Token. class ); if (annotation != null ) {
boolean needSaveSession = annotation.save();
if (needSaveSession) {
String uuid=UUID.randomUUID().toString();
log.debug("提交生成除令牌"+uuid);
request.getSession( false ).setAttribute( "token" , uuid);
}
boolean needRemoveSession = annotation.remove();
if (needRemoveSession) {
if (isRepeatSubmit(request)) {
return false ;
}
log.debug("提交移除令牌"+request.getSession().getAttribute("token" ));
request.getSession( false ).removeAttribute( "token" );
}
}
return true ;
} else {
return super .preHandle(request, response, handler);
}
} private boolean isRepeatSubmit(HttpServletRequest request) {
String serverToken = (String) request.getSession( false ).getAttribute( "token" );
if (serverToken == null ) {
return true ;
}
String clinetToken = request.getParameter( "token" );
if (clinetToken == null ) {
return true ;
}
if (!serverToken.equals(clinetToken)) {
return true ;
}
return false ;
}
}
3,在spring MVC的配置文件里注册该拦截器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"
>
<!-- 对spring org.lxh包下所有注解扫描 -->
<context:component-scan base-package="com.xxx">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository" />
</context:component-scan>
<!-- 支持spring mvc新的注解类型 详细spring3.0手册 15.12.1 mvc:annotation-driven-->
<mvc:annotation-driven /> <bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 为了使用JSTL Tag修改默认的viewClass属性 -->
<property
name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property
name="prefix"
value="/WEB-INF/views/" />
<property
name="suffix"
value=".jsp"></property>
<property
name="order"
value="1"></property>
</bean>
<!-- 拦截器 -->
<mvc:interceptors>
<!-- 用户登录拦截 -->
<bean class="com.xx.xxx.filter.StageSecurityInterceptor">
<property name="patterns" >
<list>
<value>.*/console/.*\.jhtml</value>
<value>.*/center/.*\.jhtml</value> </list>
</property>
<property name="loginView">
<value>/manage.jsp</value>
</property>
</bean>
54 <!-- 配置Token拦截器,防止用户重复提交数据 -->
55 <mvc:interceptor>
56 <mvc:mapping path="/**"/>
57 <bean class="com.xxx.framework.util.TokenInterceptor"/>
58 </mvc:interceptor>
</mvc:interceptors>
<!--
<bean id="viewResolver"
class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basenames">
<list>
<value>views-stage</value>
</list>
</property>
</bean>
-->
</beans>
4,演示demo
4.1,在跳转至某个需要加上@Token(save = true)
1 @RequestMapping("/personalForm.jhtml")
2 @Token(save = true)
public String personalForm(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) {
Account account = Account.sessionAccount();
if (account == null) {
return "redirect:/login.jsp";
}
//..........业务..............
}
4.2,在上个Controller 跳转的方法上加入${Token}
<div class="main clearfix nav center regist copyright_main5">
<h3 class="registTitle">填写身份信息</h3>
<img alt="" src="<c:url value='/platform/stage/image/regist/wave.png'/>"><br /> <img src="<c:url value='/platform/stage/image/portals/regist-info.png'/>"></img>
<c:if test="${personalInfoForm.checkState eq 2}">
<br/>
<div>
<font color="red" size="2"><span>身份认证意见:${personalInfoForm.checkOpnion}</span></font>
</div>
</c:if>
<form autocomplete="off" style="margin: 0;" id="form1" method="post" name="personalInfoForm" action="<c:url value='/center/member/savePersonalInfo.jhtml'/>" enctype="multipart/form-data">
<input type="hidden" value="${personalInfoForm.id}" name="id" />
<input type="hidden" name="token" value="${token}">
4.3,在表单提交方法的地方加上注解 @Token(remove = true)
@RequestMapping(value = "/savePersonalInfo.jhtml", method = {RequestMethod.POST})
@Token(remove = true)
public String savePersonalInfo(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap, PersonalInfo personalInfoForm) throws Exception {
DateFormat fm = new SimpleDateFormat("yyyy-MM-dd");
Date birthday = fm.parse(request.getParameter("birthday2"));
personalInfoForm.setBirthday(birthday);
Account account = Account.sessionAccount();
if(account==null){
return "redirect:/login.jsp";
}
//.....................业务.........................
}
5,完成了。
Token注解防止表单的重复提交的更多相关文章
- 使用aop注解实现表单防重复提交功能
原文:https://www.cnblogs.com/manliu/articles/5983888.html 1.这里采用的方法是:使用get请求进入表单页面时,后台会生成一个tokrn_flag分 ...
- Spring MVC表单防重复提交
利用Spring MVC的过滤器及token传递验证来实现表单防重复提交. 创建注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RU ...
- struts2 文件的上传下载 表单的重复提交 自定义拦截器
文件上传中表单的准备 要想使用 HTML 表单上传一个或多个文件 须把 HTML 表单的 enctype 属性设置为 multipart/form-data 须把 HTML 表单的method 属性设 ...
- Session机制三(表单的重复提交)
1.表单的重复提交的情况 在表单提交到一个servlet,而servlet又通过请求转发的方式响应了一个JSP页面,这个时候地址栏还保留这servlet的那个路径,在响应页面点击刷新. 在响应页面没有 ...
- HttpSession解决表单的重复提交
1). 重复提交的情况: ①. 在表单提交到一个 Servlet, 而 Servlet 又通过请求转发的方式响应一个 JSP(HTML) 页面, 此时地址栏还保留着 Serlvet 的那个路径, 在响 ...
- Struts2 - 表单的重复提交问题
用户重复提交表单在某些场合将会造成非常严重的后果.例如,在使用信用卡进行在线支付的时候,如果服务器的响应速度太慢,用户有可能会多次点击提交按钮,而这可能导致那张信用卡上的金额被消费了多次.因此,重复提 ...
- HttpSession之表单的重复提交 & 验证码
如果采用 HttpServletResponse.sendRedirct() 方法将客户端重定向到成功页面,将不会出现重复提交问题 1.表单的重复提交 1). 重复提交的情况: ①. 在表单提交到一个 ...
- php中如何防止表单的重复提交
在php中如何防止表单的重复提交?其实也有几种解决方法. 下面小编就为大家介绍一下吧.需要的朋友可以过来参考下 代码: <?php /* * php中如何防止表单的重复提交 * by www.j ...
- php-- 避免表单的重复提交
用户提交表单时可能因为网速的原因,或者网页被恶意刷新,致使同一条记录重复插入到数据库中,这是一个比较棘手的问题.我们可以从客户端和服务器端一起着手,设法避免同一表单的重复提交. 1.使用客户端脚本 提 ...
随机推荐
- jsp解决kindeditor在线编辑器struts图片上传问题
1.下载 官网下载ckeditor,解压后去掉不需要的部分,仅需保留plugin,lang,theme文件夹,这三个文件夹中用不到的东西可以删除, 比如lang文件下存放所有语言文件js,仅仅 保留e ...
- AppCompat v21 — Android 5.0之前版本设备的Material Design实现
博客原文地址:http://android-developers.blogspot.com/2014/10/appcompat-v21-material-design-for-pre.html,要想打 ...
- C#开发157
C#开发157条建议 编写高质量代码改善C#程序的157个建议[匿名类型.Lambda.延迟求值和主动求值] 摘要: 前言 从.NET3.0开始,C#开始一直支持一个新特性:匿名类型.匿名类型由v ...
- mvc4项目数据库优先的尝试
对于mvc代码优先原则,感觉真不知道为什么硬要设计这种模式,代码优先使得每次运行程序都要重建数据库,现实中这种模式有什么用呢. 数据库优先可能有好多方式,看了好久才做出来一种比较简单的.通过先添加一个 ...
- markdown实现
博客园文章markdown实现 博客园也可以使用markdown写博客了~_~ 实现方法 在博客园管理-设置-页首Html代码中加入: <!-- Markdown --> <sc ...
- js中的AMD规范
回首萧瑟,残月挂角,孤草弄影. 看了一下上一篇随笔的日期,距离上一篇日志又过去了许久.在这段时间中,我尽全力去拯救那间便利店,可惜到最后依然失败,这一次是所有的出路全部没有了,我也做了所有的努力.闲下 ...
- 利用pdf2swf将PDF转换成SWF
将PDF转换成SWF可以使用SWFTools工具中的pdf2swf(http://www.swftools.org/),CSDN快速免积分下载地址http://download.csdn.net/de ...
- mybatis配置Log4j带不出日志
使用Mybatis的时候,有些时候能输出(主要是指sql,参数,结果)日志. 无法输出日志的时候,无论怎么配置log4j,不管是properties的还是xml的,都不起作用. log4j.prope ...
- Socket的粘包处理
Socket的粘包处理 当socket接收到数据后,会根据buffer的大小一点一点的接收数据,比如: 对方发来了1M的数据量过来,但是,本地的buffer只有1024字节,那就代表socket需要重 ...
- 迷你MVVM框架 avalonjs 0.85发布
迷你MVVM框架 avalonjs 0.85发布 本版本对循环绑定做了巨大改进,感谢@soom, @limodou, @ztz, @Gaubee 提供的大量测试文件. fix scanNodes, 在 ...