zoukankan      html  css  js  c++  java
  • Web请求提交页面--防重提交

    创建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");
           }

     

     

  • 相关阅读:
    JAVAEE框架搭建所需的配置文件大全
    JPA之hibernate例子+总结
    NtDuplicateObject小解读
    黑窗口输入确定数字弹MessageBox(VirtualProtect())
    内存理解之简单的内存修改器
    注入理解之挂起线程
    银行家算法
    ReflectiveLoader分析(远程线程注入 PE修正)
    Window10中利用Windbg与虚拟机(window7)中调试驱动建立方法
    了解RabbitMQ
  • 原文地址:https://www.cnblogs.com/cqming/p/11216899.html
Copyright © 2011-2022 走看看