该例子需要用到 redis

在applocation.properties中加入redis的配置信息

server.port=8081# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=localhost
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-idle=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=
# 连接池中的最大空闲连接
spring.redis.jedis..pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=300

RedisConfig.javapackagecn.rc.config;import org.springframework.cache.annotation.CachingConfigurerSupport;import org.springframework.cache.annotation.EnableCaching;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;@Configuration
@EnableCaching // 开启注解
public class RedisConfig extends CachingConfigurerSupport {@Bean   public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();        // 配置连接工厂template.setConnectionFactory(factory);// 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();      // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括 private和publicom.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常       om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jacksonSeial.setObjectMapper(om);       // 值采用json序列化      template.setValueSerializer(jacksonSeial);        // 使用StringRedisSerializer来序列化和反序列化redis的key值template.setKeySerializer(new StringRedisSerializer());       // 设置hash key 和value序列化模式template.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(jacksonSeial);template.afterPropertiesSet();        return template;}
}

需要先启动redis功能

一、声明一个自定义的注解类

AccessLimit.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)public @interface AccessLimit { int seconds();    int maxCount();  boolean needLogin() default true;
}

二、声明一个自定义的拦截器:

AccessLimtInterceptor.java import java.util.concurrent.TimeUnit;@Component
public class AccessLimtInterceptor implements HandlerInterceptor {@Autowiredprivate RedisTemplate redisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {if (handler instanceof HandlerMethod) {HandlerMethod hm = (HandlerMethod) handler;AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);if (null == accessLimit) {return true;}int seconds = accessLimit.seconds();int maxCount = accessLimit.maxCount();boolean needLogin = accessLimit.needLogin();if (needLogin) {//判断是否登录}String ip=request.getRemoteAddr();String key = request.getServletPath() + ":" + ip ;Integer count = (Integer) redisTemplate.opsForValue().get(key);if (null == count || -1 == count) {redisTemplate.opsForValue().set(key, 1,seconds, TimeUnit.SECONDS);return true;}if (count < maxCount) {count = count+1;redisTemplate.opsForValue().set(key, count,0);return true;}if (count >= maxCount) {//                response 返回 json 请求过于频繁请稍后再试response.setCharacterEncoding("UTF-8");response.setContentType("application/json; charset=utf-8");JsonResponse  result = new JsonResponse<>();result.setCode(9999);result.setMessage("操作过于频繁");Object obj = JSONObject.toJSON(result);response.getWriter().write(JSONObject.toJSONString(obj));return false;}}return true;}
}

将 拦截器 注册到容器:WebMvcConfig.java

/*** MVC 设置**/
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {@Autowiredprivate AccessLimtInterceptor accessLimtInterceptor;@Beanpublic AccessTokenVerifyInterceptor tokenVerifyInterceptor() {return new AccessTokenVerifyInterceptor();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(accessLimtInterceptor);registry.addInterceptor(tokenVerifyInterceptor()).addPathPatterns("/**");super.addInterceptors(registry);}}

进行测试接口:

@RestController
@RequestMapping("test")
public class TestAccessLimitController {@GetMapping("accessLimit")@AccessLimit(seconds = 15, maxCount = 3) //15秒内 允许请求3次public String testAccessLimit() {return "success";}
}

浏览器请求:http://localhost:8030/test/accessLimit

返回: success

快速刷新多次后出现:

springboot 自定义拦截器 防止恶意请求相关推荐

  1. 玩转springboot:实现springboot自定义拦截器

    一.前言 在javaee中,我们经常使用filter来做拦截器,后来有了springmvc,我们使用HandlerInterceptor进行拦截,springmvc的拦截器查看这篇文章,现在有了spr ...

  2. SpringBoot自定义拦截器

  3. springboot项目拦截器中获取接口返回数据_Spring Boot自定义Annotation实现接口自动幂...

    在实际的开发项目中,一个对外暴露的接口往往会面临很多次请求,我们来解释一下幂等的概念:任意多次执行所产生的影响均与一次执行的影响相同.按照这个含义,最终的含义就是 对数据库的影响只能是一次性的,不能重 ...

  4. springboot+shiro自定义拦截器互踢问题

    shiro自定义拦截器继承AccessControllerFilter,实现session互踢机制. 应用场景: 我们经常会有用到,当A 用户在北京登录 ,然后A用户在天津再登录 ,要踢出北京登录的状 ...

  5. SpringBoot中自定义拦截器

    场景 自定义拦截器,通过继承WebMvcConfigureAdapter然后重写父类中的方法进行扩展. 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZH ...

  6. 【学习】SpringBoot之自定义拦截器

    /*** 自定义拦截器**/ @Configuration//声明这是一个拦截器 public class MyInterceptor extends WebMvcConfigurerAdapter ...

  7. springboot项目中接口防止恶意请求多次,重复请求的解决办法,适合小白

    在项目中,接口的暴露在外面,很多人就会恶意多次快速请求,那我们开发的接口和服务器在这样的频率下的话,服务器和数据库很快会奔溃的,那我们该怎么防止接口防刷呢?由于博主小白,很多都不懂,都是从网上一点一点 ...

  8. springboot-2.2.5中自定义拦截器、静态资源映射、视图控制器和其他功能

    在spring-boot-2.2.5中对MVC自动配置类进行的更改,之前的WebMvcConfigurerAdapter类声明为过时的,现在进行自定义扩展需要实现WebMvcConfigurer类重写 ...

  9. WebServices中使用cxf开发日志拦截器以及自定义拦截器

    首先下载一个cxf实例,里面包含cxf的jar包.我下的是apache-cxf-2.5.9 1.为什么要设置拦截器? 为了在webservice请求过程中,能动态操作请求和响应数据, CXF设计了拦截 ...

最新文章

  1. css表示第一个元素和最后一个元素,CSS第一个和最后一个子元素
  2. 批量按照文件大小排序并修改文件名
  3. Android Fragments 详细使用详细介绍
  4. python 音乐下载演示源代码
  5. JS替换地址栏参数值
  6. 如何使用 Node 后端创建 React 应用程序:完整指南
  7. 有计算机知识,计算机基本理论基础知识总汇
  8. 美国高级情报研究计划局(IARPA)发起公共安全问题预测机器学习挑战赛(总奖池10万美金)...
  9. html5(八) IndexedDB
  10. easyui combotree 数据太多 无法显示的处理方法
  11. centos7.4批量自动化安装(pxe、cobbler、制作自动化iso镜像);pxe安装;cobbler安装;
  12. 【原】iphone6来了,我该做点什么(兼容iphone6的方法)
  13. 【转载】史上最深(sàng)入(xīn)浅(bìng)出(kuáng)的IT术语解读【多测师_何sir】
  14. 项目管理计划Office Project 2013 日常使用
  15. python中heapq的库是什么_Python中heapq模块的用法
  16. 基于微信小程序的童装购买平台小程序
  17. Stepper Motor > 步进电机控制相关参数缩写
  18. AIWIN 心电图智能诊断Baseline【线上0.719】
  19. 未授予用户在此计算机上的请求登录类型 登录失败的解决方案
  20. Ubuntu 下安装使用飞鸽传书

热门文章

  1. c++动态规划法求解斐波那契数列
  2. 洛谷1268树的重量(树)
  3. 8代cpu核数及线程
  4. ip-guard如果服务器 IP 地址或机器名变更之后对客户端或控制台会有影响吗?
  5. 将i am a student转换成 student a am i
  6. Paintinglite迎来v2.1.2优化版本迭代,引入Pod安装
  7. MATLAB——Harris角点检测
  8. 树莓派控制4路5v继电器开关
  9. 聊下Android的专利许可和商标
  10. 以STC的单片机为例A/D做按键扫描应用原理介绍