精华内容
下载资源
问答
  • 最近负责一个后台框架的搭建,使用的是springboot redis jwt 一直哐哐写,没有想到表单重复提交的问题,晚上想结构的时候突然想起来。 上代码, 引入依赖; 使用aop做拦截 <!-- SpringBoot 拦截器 --> <...

    最近负责一个后台框架的搭建,使用的是springboot redis jwt 一直哐哐写,没有想到表单重复提交的问题,晚上想结构的时候突然想起来。
    上代码,
    引入依赖;
    使用aop做拦截

       <!-- SpringBoot 拦截器 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
    	
            <!-- SpringBoot 集成redis -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
    
    

    自定义注解

    @Inherited
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface RepeatSubmit {
    }
    
    

    编写拦截

    @Aspect
    @Component
    public class NoRepeatSubmitAop {
    
        private static final Logger logger = LoggerFactory.getLogger(NoRepeatSubmitAop.class);
    
        @Autowired
        private RedisUtil redisUtil;
    	// 这个看自己的包结构 不然不做拦截
        @Around("execution(* com.jianfan.mdt.backend.project..*Controller.*(..))&& @annotation(nos)") 
        public Object arround(ProceedingJoinPoint pjp, RepeatSubmit nos) { //RepeatSubmit自己的写注解的名字
    
            try {
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                String sessionId = RequestContextHolder.getRequestAttributes().getSessionId();
                HttpServletRequest request = attributes.getRequest();
                String key = sessionId + "-" + request.getServletPath();
                if(redisUtil.get(key)==null){
                    Object o = pjp.proceed();
                   redisUtil.set(key,key,5);//设置5秒内不能重复提交
                    return o;
                } else {
                    logger.error("重复提交");
                    return BaseResult.build(StatusCode.SERVICEERROR,StatusCode.REPAATMSG);
                }
    
            } catch (Throwable throwable) {
                logger.error("验证重复提交时出现未知异常!");
                return BaseResult.build(StatusCode.SERVICEERROR,StatusCode.REPAATMSGEXCEPT);
            }
    
        }
    
    }
    

    注解使用
    在这里插入图片描述
    测试结果
    在这里插入图片描述
    点赞加关注;免费分享众多开源项目;

    展开全文
  • SpringBoot防止表单重复提交(一) 一、重复提交的原因 用户表单登陆后直接转发到相应的页面,这是刷新页面会重复发送上次的请求,也就是会再次提交表单(浏览器会弹出表单重复提交的弹窗) 二、解决方法(存在漏洞) 在...

    SpringBoot防止表单重复提交(一)

    一、重复提交的原因

    用户表单登陆后直接转发到相应的页面,这是刷新页面会重复发送上次的请求,也就是会再次提交表单(浏览器会弹出表单重复提交的弹窗)
    

    二、解决方法(存在漏洞)

    1. 在后台登录成功后重定向到指定页面
    @PostMapping("/login")
    public String login(@RequestParam("name") String name, @RequestParam("pwd")String pwd, Map<String,Object> map){
        if (StringUtils.isEmpty(name) || StringUtils.isEmpty(pwd)){
            map.put("msg","error");
            return "login";
        }
        // 成功跳转到success后,如果刷新页面。会提示重新提交表单的请求
        // return "success";
        // 为了防止表单重复提交,这里将请求重定向到主页
        return "redirect:/main.html";
    }
    
    1. 追加映射
    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
       return new WebMvcConfigurer() {
           // 页面跳转,映射
           @Override
           public void addViewControllers(ViewControllerRegistry registry) {
    			registry.addViewController("/main.html").setViewName("success");
           }
    }
    

    三、漏洞

    上面的方法存在漏洞,如果直接访问main.html则不需要登陆就能访问

    四、拦截器解决漏洞

    1. 自定义拦截器类
    /**
     * 自定义拦截器
     */
    public class MyIntercept implements HandlerInterceptor {
        /**
         *在业务处理器处理请求之前被调用
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            Object username = request.getSession().getAttribute("username");
            if(username == null)
            {   // 未登录,返回转发到登录页面
                request.setAttribute("msg","先登录");
                request.getRequestDispatcher("/index.html").forward(request,response);
                return false;
            }
            return true;
        }
        /**
         *在业务处理器处理请求执行完成后,生成视图之前执行
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    
        }
        /**
         *在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面)
         */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    
        }
    }
    
    1. 注入拦截器
    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
         return new WebMvcConfigurer() {
             // 页面跳转,映射
             @Override
             public void addViewControllers(ViewControllerRegistry registry) {
                 registry.addViewController("/").setViewName("login");
                 registry.addViewController("/index.html").setViewName("login");
                 registry.addViewController("/change.html").setViewName("login");
                 registry.addViewController("/main.html").setViewName("success");
             }
    
             // 拦截器
             @Override
             public void addInterceptors(InterceptorRegistry registry) {
                 // 注册拦截器
                 registry.addInterceptor(new MyIntercept())
                         // 设置拦截的请求
                         .addPathPatterns("/**")
                         // 设置不拦截的请求
                         // 静态资源不需要设置,springboot已经做好了处理
                         .excludePathPatterns("/index.html","/","/change.html","/login");
    
             }
    }
    
    展开全文
  • throw new Exception("你提交的太频繁了,请稍后再试"); } } else { this.redisUtil.set(key, String.valueOf(now)); Object proceed = pjp.proceed(); return proceed; } } } }  
    
    
    
    import java.util.Objects;
    import javax.servlet.http.HttpServletRequest;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    @Aspect
    @Component
    public class NoRepeatSubmitAop {
        Logger logger = LoggerFactory.getLogger(this.getClass());
        int time = 3000;
        @Autowired
        private RedisUtil redisUtil;
    
        public NoRepeatSubmitAop() {
        }
    
        @Around("execution(* com.hl..controller.*.*(..))")
        public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
            HttpServletRequest request = ((ServletRequestAttributes)Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
            String method = request.getMethod();
            if (!method.equals("POST") && !method.equals("PUT")) {
                Object proceed = pjp.proceed();
                return proceed;
            } else {
                String ip = BaseUtil.getIpAddress(request);
                String url = request.getRequestURL().toString();
                long now = System.currentTimeMillis();
                String key = "REQUEST_FORM_" + ip;
                if (this.redisUtil.hasKey(key)) {
                    long lastTime = ConvertUtil.parseLong(this.redisUtil.get(key));
                    if (now - lastTime > (long)this.time) {
                        this.redisUtil.set(key, String.valueOf(now));
                        Object proceed = pjp.proceed();
                        return proceed;
                    } else {
                        throw new Exception("你提交的太频繁了,请稍后再试");
                    }
                } else {
                    this.redisUtil.set(key, String.valueOf(now));
                    Object proceed = pjp.proceed();
                    return proceed;
                }
            }
        }
    }
    

     

    展开全文
  • 一、背景 二、token.java 三、拦截器 四、应用实例

     

    一、背景

     

    二、token.java

     

     

    三、拦截器

     

     

    四、应用实例

     

     

    展开全文
  • 文章目录前言装备Core-Code新增注解@...SpringBoot防止表单重复提交。基于拦截器对带注解的请求进行拦截,处理。 后面总结一下为什么要如此使用。 应用场景: 使用浏览器后退按钮重复之前的操作...
  • 1.自定义注解@NoRepeatSubmit 标记所有Controller中提交的请求 2.通过AOP对所有标记了@NoRepeatSubmit 的方法进行拦截 3.在业务方法执行前,获取当前用户的token或者JSessionId+当前请求地址,作为一个唯一的key,去...
  • SpringBoot如何防止重复提交

    万次阅读 2019-06-12 21:32:46
    场景:同一个用户在2秒内对同一URL的提交视为重复提交。 思考逻辑: 1.从数据库方面考虑,数据设计的时候,某些数据有没有唯一性,如果有唯一性,要考虑设置唯一索引,可以避免脏数据。 2.从应用层面考虑,首先...
  • springboot使用redis防止表单重复提交 引入redis依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <...
  • 什么是表单重复提交 什么是表单重复提交 各位大哥好,首先介绍一下什么是表单重复提交.(原谅我中英文句点不分,是因为开发的时候把中文的符号也切换成了英文的)一个场景就是小弟我在实习的时候做的第一个前后端分离的...
  • 叙述 平时开发的项目中可能会出现下面这些情况: ... 由于网速等原因造成页面卡顿,用户重复刷新提交页面。 黑客或恶意用户使用postman等...这些情况都会导致表单重复提交,造成数据重复,增加服务器负载,严重...
  • springboot2.1+redis+拦截器 防止表单重复提交详细完整介绍,所用到的文件都上传了,下载即可使用。自己花了半天整理,并且测试通过,使用在实际项目中的,希望对每一个下载的朋友有帮助。
  • 首先需要说明的是之前的防止重复提交是指:一次请求完成之前防止重复提交,当然扩展下就可以做到会话间防止重复提交,还可以扩展为某个时间段或者永久防止重复提交(这个我就不实现了),下面我来扩展一下相同会话...
  • * 测试重复提交 * 这里我们将time设置为3秒,也就是3秒内我们同一个请求,同一个token,同一个参数不能重复请求。 * @param param 参数 */ @GetMapping("/testRepeatSubmit"...
  • import java.lang.annotation.ElementType; import java.lang.annotation.Retention;... * @description: 防止表单重复提交 * @author: 云晓得峰 **/ @Target(ElementType.METHOD) // 作用到方法上 @Ret.

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,538
精华内容 615
关键字:

springboot防止表单重复提交

spring 订阅