springmvc 用拦截器+token防止重复提交
一,原理:
1,在进入到提交页面时,使用拦截器拦截在进入此方法前,生成一个token,放到session中,
@RequestMapping(value = "/{id}/details")
@FormToken(produce = true)
public Object details(@PathVariable String id, HttpServletRequest request){
Map<String,Object> map = new HashMap<>();
GameInfo gameInfo;
int count;
try {
gameInfo = gameInfoService.get(id, -1);
// 使用此游戏的活动数
count = activityService.getCountByGid(id);
gameInfo.setCount(count);
} catch (TException e) {
LOGGER.debug("获取指定游戏详情失败!!", e);
return new MessageEntity.Builder(request).msg("跳转预览页面失败").code(201).success(false)
.create();
}
map.put("gameInfo",gameInfo);
return new MessageEntity.Builder(request).msg("success").code(201).content(map).success(true)
.create();
}
@FormToken此标签:
package com.caobug.client.annotation; import java.lang.annotation.*; /**
* TOKEN生成与删除
* Created by caobug on 14-8-15.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FormToken { /**
* 是否在页面生成TOKEN
*
* @return
*/
boolean produce() default false; /**
* 是否删除旧 TOKEN
*
* @return
*/
boolean remove() default false;
}
实现一个拦截器接口
package com.caobug.client.support.interceptor; import com.caobug.client.annotation.FormToken;
import com.caobug.client.support.MessageCode;
import com.caobug.client.support.MessageEntity;
import com.caobug.client.support.utils.TokenUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.ResponseBody;
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.io.PrintWriter;
import java.lang.reflect.Method; /**
* Token 拦截器
* <p/>
* Created by caobug on 14-8-15.
*/
public class FormTokenInterceptor extends HandlerInterceptorAdapter { public final static String TOKEN_NAME = "resubmitToken"; /**
* 方法处理前处理
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
FormToken formToken = method.getAnnotation(FormToken.class);
if (null != formToken) {
if ((formToken.produce() && formToken.remove()) || (!formToken.produce() && !formToken.remove())) {
throw new RuntimeException("请不要在同一个方法上同时注解:@FormToken(remove = true/false, produce = true/false)");
} else if (formToken.produce()) {
request.getSession().setAttribute(TOKEN_NAME, TokenUtils.getToken());
} else if (formToken.remove()) {
String serverToken = (String) request.getSession().getAttribute(TOKEN_NAME);
String clientToken = request.getParameter(TOKEN_NAME);
request.getSession().removeAttribute(TOKEN_NAME); // remove token
if (!StringUtils.equals(serverToken, clientToken)) {
if (null != method.getAnnotation(ResponseBody.class)) { // JSON
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
PrintWriter out = response.getWriter();
out.print(new ObjectMapper().writeValueAsString(new MessageEntity.Builder(null).
code(MessageCode.SEND_MULTIPLE).msg("无效请求,请刷新页面后重试").create()));
out.flush();
out.close();
} else { // 普通页面
request.getRequestDispatcher("/error/invalidRequest").forward(request, response);
}
return false;
}
}
}
return super.preHandle(request, response, handler);
}
}
xml配置:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="interceptors">
<list>
<bean class="com.caobug.client.support.interceptor.FormTokenInterceptor"/>
</list>
</property>
</bean>
2,在提交页面中接收到这个值:
<input type="hidden" name="token" value="${token}" />
3,提交处理;
@RequestMapping("/SaveDataController/saveData")
@ResponseBody
@FormToken(remove=true)
public void saveData(HttpServletRequest request,HttpServletResponse response,
String tablename,String trowkey,String columns,
String indextablename,String irowkey,String icolumns,
String task_id,String savetype,String memoryCodes){
System.out.println(task_id);
saveDataService.saveData(task_id,savetype,memoryCodes,tablename, trowkey, columns, indextablename, irowkey, icolumns);
}
4,第一次提交时,在还没进入到提交页面时,就在服务器端生成一个token(拦截器做出此动作),把此token传递给提交页面,点击“提交”按钮,进入到处理的method方法,拦截此方法,在拦截器中把session的值清空,对比两个token,
http://www.cnblogs.com/hdwpdx/archive/2016/03/29/5333943.html
springmvc 用拦截器+token防止重复提交的更多相关文章
- Struts2 06--系统拦截器防止数据重复提交
一.拦截器简要概述 拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作.拦截是AOP的一种实现策略. 在W ...
- spring MVC 后台token防重复提交解决方案
看到公司有个部门提出了这个问题,补个粗略的解决方案... 1.编写拦截器 /** * Description: 防止重复提交 * * @Author liam * @Create Date: 2018 ...
- 161116、springmvc自己实现防止表单重复提交(基于注解)
原理:在去某个页面直接生成一个随机数(这里使用的是UUID)并放入session中,用户提交表单时将这个随机数传入服务端与session中的值进行比较,如果不不存在或不相等,则认为是重复提交:如果相等 ...
- struts2中token防止重复提交表单
struts2中token防止重复提交表单 >>>>>>>>>>>>>>>>>>>&g ...
- SpringMVC利用拦截器防止SQL注入
引言 随着互联网的发展,人们在享受互联网带来的便捷的服务的时候,也面临着个人的隐私泄漏的问题.小到一个拥有用户系统的小型论坛,大到各个大型的银行机构,互联网安全问题都显得格外重要.而这些网站的背后,则 ...
- SpringMVC:拦截器
SpringMVC:拦截器 概述 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理.开发者可以自己定义一些拦截器来实现特定的功能. 过 ...
- springmvc的拦截器
什么是拦截器 java里的拦截器是动态拦截action调用的对象.它提供了一种机制可以使 ...
- SpringMVC经典系列-14自己定义SpringMVC的拦截器---【LinusZhu】
注意:此文章是个人原创.希望有转载须要的朋友们标明文章出处.假设各位朋友们认为写的还好,就给个赞哈.你的鼓舞是我创作的最大动力,LinusZhu在此表示十分感谢,当然文章中如有纰漏,请联系linusz ...
- 基于注解风格的Spring-MVC的拦截器
基于注解风格的Spring-MVC的拦截器 Spring-MVC如何使用拦截器,官方文档只给出了非注解风格的例子.那么基于注解风格如何使用拦截器呢? 基于注解基本上有2个可使用的定义类,分别是Defa ...
随机推荐
- [NOIP2013] 火柴排队(归并排序)
题目描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2 其中 ai 表示 ...
- JS 控制CSS样式表
JS控制CSS所使用的方法: <style> .rule{ display: none; } </style> 你想要改变把他的display属性由none改为inline. ...
- 【转载】 Java 7之基础 - 强引用、弱引用、软引用、虚引用
原文地址:http://blog.csdn.net/mazhimazh/article/details/19752475 1.强引用(StrongReference) 强引用是使用最普遍的引用.如果一 ...
- SynchronousQueue类
介绍 Java 6的并发编程包中的SynchronousQueue是一个没有数据缓冲的BlockingQueue,生产者线程对其的插入操作put必须等待消费者的移除操作take,反过来也一样.不像Ar ...
- HTML day0
HTML 标签 <article>标签:标签规定独立的自包含内容.一篇文章应有其自身的意义,应该有可能独立于站点的其余部分对其进行分发. <article> 元素的潜在来源: ...
- win版本对比
Win+R 输入:slmgr.vbs -dlv 显示:最为详尽的激活信息,包括:激活ID.安装ID.激活截止日期slmgr.vbs -dli 显示:操作系统版本.部分产品密钥.许可证状态slmgr.v ...
- entity framework自动迁移
第一步,建立测试项目,普通的WinForm类型,EntityMigration: 第二步,从NuGet为项目添加MySql.Data.Entity,由Oracle提供,我选择人气高的: 第三步,建立实 ...
- spring mvc fastJson 自定义类型转换(返回数据) 实现对ObjectId类型转换
json用的alibaba fastJson ValueFilter filter = new ValueFilter() { @Override public Object process(Obje ...
- 崽崽帮www.zaizaibang.com精选2
崔其亮-儿科专科 智慧熊北京丰台幼儿园——秋游活动 周边景点——哈尔滨旅游攻略 月是故乡明丨那些买给自己吃的常德手工月饼老店 [周末乐游]南京最美10所大学,这个周末一起逛一逛吧 彭韶-儿科二门诊 [ ...
- ajax-向服务器发送请求
ajax-向服务器发送请求 1.将请求发送到服务器,使用XMLHttpRequest对象的 open() 和 send() 方法. xmlhttp. open(method,url,async ...