QM.C

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
创建TokenForm注解,标记需要防重提交页面(View

package org.chu.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;
 
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TokenForm {
       //如果create为true,表示是一个跳转到增加页面的请求
       //boolean create() default false;
       //如果是remove为true,表示是一个增加提交的请求
       boolean remove() default false;
       
}

 

 

 

创建拦截器
package org.chu.interceptor;
 
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
 
import org.chu.annotation.TokenForm;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
 
public class TokenInterceptor implements HandlerInterceptor {
 
       @Override
       public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         

            //第一步:如果是一个增加页面的请求,就创建一个Token
            //问题:如何标志请求的方法是一个增加的方法呢?通过注解标识
            //HandlerMethod对象可以获得请求准备要调用的方法的方法信息

           List<String> tokenPool=null;
                HandlerMethod hm = (HandlerMethod) handler;
                TokenForm tokenForm = hm.getMethodAnnotation(TokenForm.class);
                //判断注解是否为空
                if(tokenForm!=null) {
                        HttpSession session = request.getSession();
              //问题:如果多个请求页面使用的sessionToken是同一个时,会出现相互覆盖的情况
              //解决:使用一个集合来存储sessionToken。即Token池
              //需要设计Token池的大小,当Token过大时,删除最早的sessionToken(这里没有设计)
                        if(session.getAttribute("tokenPool")==null) {
                                 tokenPool = new ArrayList<>();
                        }else {
                                 tokenPool=(List<String>) session.getAttribute("tokenPool");
                        }
                        //只要进入或者提交都要创建一个新的Token放在session里面
                        String sessionToken = UUID.randomUUID().toString();
                        //将创建的Token放在会话的tokenPool里面
                        tokenPool.add(sessionToken);
                        //将创建的Token放在会话中返回页面
                        session.setAttribute("sessionToken", sessionToken);
                        session.setAttribute("tokenPool", tokenPool);
                        //remove为true,表示一个提交增加的请求
                        if(tokenForm.remove()) {
                    //判断请求表单的token和token池里面的token是否相同
                                 String formToken = request.getParameter("formToken");
                                 List<String> resultTokenPool = (List<String>) session.getAttribute("tokenPool");
                                 boolean flag = false;
                                 for (String token : resultTokenPool) {
                                         if(token.equals(formToken)) {
                             //如果发现token池有对应的token就移除
                                                resultTokenPool.remove(token);
                                                  flag = true;
                                                  break;
                                         }
                                 }
                    //如果表单的token在token池里面没有,就跳转到指定的页面
                    //token.invoke:页面路径

                       //在提交页面表单中添加<input type="hidden" name="formToken" value="${sessionScope.sessionToken }">
            //<input  type="hidden"name="token.invoke"value="${pageContext.request.contextPath}/role/toRoleAdd">

 
                                 if(flag==false) {
                                        response.sendRedirect(request.getParameter("token.invoke"));
                                         return false;
                                 }
                        }
                        
                }
                
                return true;
       }
 
       @Override
       public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                        ModelAndView modelAndView) throws Exception {
                // TODO Auto-generated method stub

  } 

@Override 
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
              Exception ex) throws Exception {

        // TODO Auto-generated method stub
  }
}

 

 

 

在配置文件(config)中加入拦截器
@Override
       public void addInterceptors(InterceptorRegistry registry) {
 
                
                TokenInterceptor tokenInterceptor = new TokenInterceptor();
                registry.addInterceptor(tokenInterceptor )
                //拦截所有请求
                .addPathPatterns("/**")
                //排除登录不拦截
                .excludePathPatterns("/user/login")
               //排除注销不拦截
                .excludePathPatterns("/user/undo");
       }

 

 

posted on 2019-07-20 10:35  QM.C  阅读(223)  评论(0编辑  收藏  举报