SpringBoot中自定义注解实现控制器访问次数限制实例
今天给大家介绍一下SpringBoot中如何自定义注解实现控制器访问次数限制。
在Web中最经常发生的就是利用恶性URL访问刷爆服务器之类的攻击,今天我就给大家介绍一下如何利用自定义注解实现这类攻击的防御操作。
其实这类问题一般的解决思路就是:在控制器中加入自定义注解实现访问次数限制的功能。
具体的实现过程看下面的例子:
步骤一:先定义一个注解类,下面看代码事例:
packageexample.controller.limit; importorg.springframework.core.Ordered; importorg.springframework.core.annotation.Order; importjava.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented //最高优先级 @Order(Ordered.HIGHEST_PRECEDENCE) public@interfaceRequestLimit{ /** * *允许访问的次数,默认值MAX_VALUE */ intcount()defaultInteger.MAX_VALUE; /** * *时间段,单位为毫秒,默认值一分钟 */ longtime()default60000; }
步骤二:定义一个异常类,用来处理URL攻击时产生的异常问题,下面看代码事例:
packageexample.controller.exception; publicclassRequestLimitExceptionextendsException{ privatestaticfinallongserialVersionUID=1364225358754654702L; publicRequestLimitException(){ super("HTTP请求超出设定的限制"); } publicRequestLimitException(Stringmessage){ super(message); } }
步骤三:定义一个注解的具体实现类,下面看代码事例:
packageexample.controller.limit; importexample.controller.exception.RequestLimitException; importorg.aspectj.lang.JoinPoint; importorg.aspectj.lang.annotation.Aspect; importorg.aspectj.lang.annotation.Before; importorg.slf4j.Logger; importorg.slf4j.LoggerFactory; importorg.springframework.stereotype.Component; importjavax.servlet.http.HttpServletRequest; importjava.util.HashMap; importjava.util.Map; importjava.util.Timer; importjava.util.TimerTask; importjava.util.concurrent.TimeUnit; @Aspect @Component publicclassRequestLimitContract{ privatestaticfinalLoggerlogger=LoggerFactory.getLogger("RequestLimitLogger"); privateMapredisTemplate=newHashMap (); @Before("within(@org.springframework.stereotype.Controller*)&&@annotation(limit)") publicvoidrequestLimit(finalJoinPointjoinPoint,RequestLimitlimit)throwsRequestLimitException{ try{ Object[]args=joinPoint.getArgs(); HttpServletRequestrequest=null; for(inti=0;i 0){ Timertimer=newTimer(); TimerTasktask=newTimerTask(){//创建一个新的计时器任务。 @Override publicvoidrun(){ redisTemplate.remove(key); } }; timer.schedule(task,limit.time()); //安排在指定延迟后执行指定的任务。task:所要安排的任务。10000:执行任务前的延迟时间,单位是毫秒。 } if(count>limit.count()){ //logger.info("用户IP["+ip+"]访问地址["+url+"]超过了限定的次数["+limit.count()+"]"); thrownewRequestLimitException(); } }catch(RequestLimitExceptione){ throwe; }catch(Exceptione){ logger.error("发生异常:",e); } } }
步骤四:实现一个控制类,并添加使用注解功能。下面看代码事例:
packageexample.controller; importexample.controller.limit.RequestLimit; importorg.springframework.stereotype.Controller; importorg.springframework.ui.ModelMap; importorg.springframework.web.bind.annotation.RequestMapping; importorg.springframework.web.bind.annotation.ResponseBody; importjavax.servlet.http.HttpServletRequest; @Controller publicclassURLController{ @RequestLimit(count=10,time=5000) @RequestMapping("/urltest") @ResponseBody publicStringtest(HttpServletRequestrequest,ModelMapmodelMap){ return"aaa"; } }
其中count指的是规定时间内的访问次数,time指的就是规定时间,单位为毫秒。
这样就实现了在控制器这个层次上面的url拦截了。不过这里有个问题,就是如果想在每一个URL页面上面都进行这样的拦截,这种方法明显是不够的。因为我们不可能在每个控制器上面都加上url拦截的注解,所以这种方法只适合在某些特定的URL拦截上面使用它们。
那如何实现过滤器级别上面的URL访问拦截呢?这里先给大家卖一个关子,我将会在下一节中给大家介绍如何利用过滤器实现URl访问拦截,并且利用JPA实现ip黑名单的功能,加入IP黑名单后就不可以进行任何URL的访问了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。