原理:在去某個頁面直接生成一個隨機數(這里使用的是UUID)並放入session中,用戶提交表單時將這個隨機數傳入服務端與session中的值進行比較,如果不不存在或不相等,則認為是重復提交;如果相等則不是重復提交。
實現技術:采用springmvc的攔截器統一處理
下面實現(五步)
第一步:
package com.xxx.utils.anti_resubmit;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 防止重復提交用
* @author wsc
* 2016年12月5日
*/
@Target(ElementType.METHOD)//如果用在類上,將此行注釋
@Retention(RetentionPolicy.RUNTIME)
public @interface Token {
boolean save() default false;
boolean remove() default false;
}
第二步:攔截器
package com.xxx.inteceptors;
import java.lang.reflect.Method;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.xxx.annotation.anti_resubmit.Token;
/**
* 防止重復提交
* @author wsc
* 2016年12月5日
*/
public class TokenInterceptor extends HandlerInterceptorAdapter {
private static final String TOKEN_NAME = "token";
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
if(handler instanceof HandlerMethod){
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
Token annotation = method.getAnnotation(Token.class);
if(annotation != null){
boolean need2SaveSession = annotation.save();
if(need2SaveSession){
request.getSession(false).setAttribute("token", UUID.randomUUID().toString());
}
boolean need2RemoveSession = annotation.remove();
if(need2RemoveSession){
if(isRepeatSubmit(request)){
return false;
}
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_NAME);//服務端
if(serverToken == null){
return true;
}
String clientToken = request.getParameter(TOKEN_NAME);//客戶端
if(clientToken == null){
return true;
}
if(!serverToken.equals(clientToken)){
return true;
}
return false;
}
}
第三步:
springmvc配置文件(攔截器)
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<!-- <ref bean="wechatLoginInterceptor"/> -->
<ref bean="tokenInteceptor"/>
</list>
</property>
</bean>
<bean id="tokenInteceptor" class="com.xxx.inteceptors.TokenInterceptor"/>
第四步:
controller中使用
@RequestMapping("/add.jspf")
@Token(save=true)
public String add() {
//省略
return TPL_BASE + "index";
}
@RequestMapping("/save.jspf")
@Token(remove=true)
public void save() {
//省略
}
第五步:
頁面
<input type="text" name="token" value="${token}"/>