基于springmvc 通过注解方式实现token(重复提交)验证
< 返回列表时间: 2019-09-03来源:OSCHINA
token验证,记得当年struts/struts2的时候,现在页面设置token,然后在
action进行验证,而在springmvc下,有更简单的方法

具体实现如下:
/**
* 防止重复提交
* @author 傻根她弟
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@Order(Ordered.LOWEST_PRECEDENCE)
public @interface Token {

}

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import cn.he.annotation.Token;
import com.alibaba.fastjson.JSON;

@Aspect
@Component
public class TokenAspect {
private static final Logger logger = LoggerFactory.getLogger("TokenAspect");
@Before("within(@org.springframework.web.bind.annotation.RestController *) && @annotation(token)")
public void requestToken(final JoinPoint joinPoint, Token token) throws RequestTokenException {
try {
Object[] args = joinPoint.getArgs();

if(this.repeatDataValidator(args)){
throw new Exception("请勿重复提交数据");
}

} catch (RequestTokenException e) {
throw e;
} catch (Exception e) {
logger.error("发生异常: ", e);
}
}


/**
* 验证同一个url数据是否相同提交 ,相同返回true
* @param httpServletRequest
* @return
*/
private boolean repeatDataValidator(Object[] args)
{
HttpServletRequest request = null;
List<Object> new_obj = new ArrayList<Object>();

for (int i = 0; i < args.length; i++) {
if (args[i] instanceof HttpServletRequest) {
request = (HttpServletRequest) args[i];
break;
}
}

for (int i = 0; i < args.length; i++) {
if (args[i] instanceof HttpServletRequest) {
continue;
}
if (args[i] instanceof BindingResult) {
continue;
}
new_obj.add(args[i]);
}

if (request == null) {
throw new RequestTokenException("0","调用Token注释,方法中缺失HttpServletRequest参数");
}

String params= this.toJson(new_obj);
String url=request.getRequestURI();
Map<String,String> map=new HashMap<String,String>();
map.put(url, params);
String nowUrlParams=map.toString();//
Object preUrlParams=request.getSession().getAttribute("_req_repeatData");
if(preUrlParams==null)//如果上一个数据为null,表示还没有访问页面
{
request.getSession().setAttribute("_req_repeatData", nowUrlParams);
return false;
}
else//否则,已经访问过页面
{
if(preUrlParams.toString().equals(nowUrlParams))//如果上次url+数据和本次url+数据相同,则表示城府添加数据
{
return true;
}
else//如果上次 url+数据 和本次url加数据不同,则不是重复提交
{
request.getSession().setAttribute("_req_repeatData", nowUrlParams);
return false;
}

}
}

/**
* Object转成JSON数据
*/
private String toJson(Object object){
if(object instanceof Integer || object instanceof Long || object instanceof Float ||
object instanceof Double || object instanceof Boolean || object instanceof String){
return String.valueOf(object);
}
return JSON.toJSONString(object);
}
}

简单明了,前台页面什么也不用加,只需要在controller对应的方法上加上注解@Token该方法就生效。不过前提是TokenAspect 要生效,至于怎么让它生效,懂点spring的应该都会设置,此处就不再赘述了
热门排行