Skip to content

Instantly share code, notes, and snippets.

@hallkk
Forked from jarod-chan/CheckToken.java
Created August 20, 2016 14:57
Show Gist options
  • Save hallkk/13c358de74a5714be4a0e72a272b5515 to your computer and use it in GitHub Desktop.
Save hallkk/13c358de74a5714be4a0e72a272b5515 to your computer and use it in GitHub Desktop.
spring aop 处理重复提交
package cn.fyg.pa.interfaces.module.shared.token.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*校验token是否有效
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CheckToken {
String redirectUrl() default "";
}
package cn.fyg.pa.interfaces.module.shared.token.bean;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;
import cn.fyg.pa.interfaces.module.shared.message.MessagePasser;
import cn.fyg.pa.interfaces.module.shared.session.SessionUtil;
import cn.fyg.pa.interfaces.module.shared.token.annotation.CheckToken;
@Component
public class CheckTokenAdvice {
@Resource
private HttpServletRequest request;
@Resource
SessionUtil sessionUtil;
@Resource
MessagePasser messagePasser;
public String around(ProceedingJoinPoint pjp,CheckToken checkToken) throws Throwable{
Object object = request.getParameter("session_token");
String token=object!=null? object.toString():null;
if(!sessionUtil.checkToken(token)){
messagePasser.setMessage("重复提交数据导致数据重复,请重新填写。(请不要使用浏览器后退功能!)");
return checkToken.redirectUrl();
}
Object proceed = pjp.proceed();
return proceed.toString();
}
}
package cn.fyg.pa.interfaces.module.shared.token.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*注解controller的方法,表示产生一个token
*用于防止重复提交
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CreateToken {
/**
* map 参数的参数位置 用于向界面注入token
* 采用spring aop的时候 ,无法用配置的方式取得controller类里map参数
* 所以在注解里指定
* 可能可以通过参数名在xml里直接提取map参数,有待进一步验证
* @return
*/
int mapIndex() default -1;
}
package cn.fyg.pa.interfaces.module.shared.token.bean;
import java.util.Map;
import javax.annotation.Resource;
import org.aspectj.lang.JoinPoint;
import org.springframework.stereotype.Component;
import cn.fyg.pa.interfaces.module.shared.session.SessionUtil;
import cn.fyg.pa.interfaces.module.shared.token.annotation.CreateToken;
@Component
public class CreateTokenAdvice {
@Resource
SessionUtil sessionUtil;
public void after(JoinPoint jp,CreateToken createToken){
if(createToken.mapIndex()>=0){
@SuppressWarnings("unchecked")
Map<String,Object> map=(Map<String, Object>) jp.getArgs()[createToken.mapIndex()];
String token = sessionUtil.createToken();
map.put("session_token", token);
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:annotation-config/>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<aop:config>
<!--过滤infterfaces 里任何一个ctl类 记录日志 -->
<aop:aspect id="aspect" ref="logAdvice">
<aop:pointcut expression="execution(* cn.fyg.pa.interfaces.module..*Ctl.*(..))" id="pointCut"/>
<aop:before method="before" pointcut-ref="pointCut"/>
</aop:aspect>
<!--过滤会产生数据重复保存的页面,保证数据不会被重复提交 -->
<aop:aspect id="createToken" ref="createTokenAdvice">
<aop:pointcut expression="execution(@cn.fyg.pa.interfaces.module.shared.token.annotation.CreateToken * *(..)) and @annotation(createToken)" id="createTokenCut"/>
<aop:after method="after" arg-names="createToken" pointcut-ref="createTokenCut"/>
</aop:aspect>
<aop:aspect id="checkToken" ref="checkTokenAdvice">
<aop:pointcut expression="execution(@cn.fyg.pa.interfaces.module.shared.token.annotation.CheckToken * *(..)) and @annotation(checkToken)" id="checkTokenCut"/>
<aop:around method="around" arg-names="checkToken" pointcut-ref="checkTokenCut"/>
</aop:aspect>
</aop:config>
</beans>
解决重复提交问题
-- 采用spring aop的方式用注解来解决重复提交的问题
1.用CreateToken注解产生一个随机字串,并保存在session中
2.用CheckToken注解在保存方法前校验session中的随机字串
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment