原理:在新建页面中Session保存token随机码,当保存时验证,通过后删除,当再次点击保存时由于服务器端的Session中已经不存在了,所有无法验证通过。
1.新建注解:
04 |
*
在新建页面方法上,设置needSaveToken()为true,此时拦截器会在Session中保存一个token, |
06 |
*
<input type="hidden" name="token" value="${token}"> |
08 |
*
保存方法需要验证重复提交的,设置needRemoveToken为true |
12 |
*
@date: 2013-6-27上午11:14:02 |
15 |
@Target(ElementType.METHOD) |
16 |
@Retention(RetentionPolicy.RUNTIME) |
17 |
public @interface AvoidDuplicateSubmission
{ |
18 |
boolean needSaveToken() default false; |
19 |
boolean needRemoveToken() default false; |
2. 新建拦截器
07 |
*
@date: 2013-6-27上午11:19:05 |
09 |
public class AvoidDuplicateSubmissionInterceptor extends HandlerInterceptorAdapter
{ |
10 |
private static final Logger
LOG = Logger.getLogger(AvoidDuplicateSubmissionInterceptor.class); |
13 |
public boolean preHandle(HttpServletRequest
request, |
14 |
HttpServletResponse
response, Object handler) throws Exception
{ |
16 |
User
user = UserUtil.getUser(); |
18 |
HandlerMethod
handlerMethod = (HandlerMethod) handler; |
19 |
Method
method = handlerMethod.getMethod(); |
21 |
AvoidDuplicateSubmission
annotation = method.getAnnotation(AvoidDuplicateSubmission.class); |
22 |
if (annotation
!= null)
{ |
23 |
boolean needSaveSession
= annotation.needSaveToken(); |
24 |
if (needSaveSession)
{ |
25 |
request.getSession(false).setAttribute("token",
TokenProcessor.getInstance().generateToken()); |
28 |
boolean needRemoveSession
= annotation.needRemoveToken(); |
29 |
if (needRemoveSession)
{ |
30 |
if (isRepeatSubmit(request))
{ |
31 |
LOG.warn("please
don't repeat submit,[user:" +
user.getUsername() + ",url:" |
32 |
+
request.getServletPath() + "]"); |
35 |
request.getSession(false).removeAttribute("token"); |
42 |
private boolean isRepeatSubmit(HttpServletRequest
request) { |
43 |
String
serverToken = (String) request.getSession(false).getAttribute("token"); |
44 |
if (serverToken
== null)
{ |
47 |
String
clinetToken = request.getParameter("token"); |
48 |
if (clinetToken
== null)
{ |
51 |
if (!serverToken.equals(clinetToken))
{ |
3. 在Spring中配置
1 |
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> |
2 |
<property name="interceptors"> |
4 |
<bean class="com.sohu.tv.crm.aop.UserLogInterceptor"/> |
5 |
<bean class="com.sohu.tv.crm.aop.AvoidDuplicateSubmissionInterceptor"/> |
4. 在相关方法中加入注解:
1 |
@RequestMapping("/save") |
2 |
@AvoidDuplicateSubmission(needRemoveToken
= true) |
3 |
public synchronized ModelAndView
save(ExecutionUnit unit, HttpServletRequest request, HttpServletResponse response) |
6 |
@RequestMapping("/edit") |
7 |
@AvoidDuplicateSubmission(needSaveToken
= true) |
8 |
public ModelAndView
edit(Integer id, HttpServletRequest request) throws Exception
{ |
5.在新建页面中加入
<input type="hidden" name="token" value="${token}">