基于springmvc 通过注解方式实现token(重复提交)验证

原创
2019/09/03 14:47
阅读数 201

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的应该都会设置,此处就不再赘述了

展开阅读全文
加载中

作者的其它热门文章

打赏
0
3 收藏
分享
打赏
0 评论
3 收藏
0
分享
返回顶部
顶部