Spring Boot 防止接口被恶意刷新、暴力请求

[复制链接]
发表于 2023-2-19 11:49:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
​在实际项目使用中,必须要考虑服务的安全性,当服务部署到互联网以后,就要考虑服务被恶意请求和暴力攻击的情况,下面的教程,通过Spring Boot提供的HandlerInterceptor和Redis 针对 Url + ip在一定时间内访问的次数来将ip禁用,可以根据自己的业务需求进行相应的修改,以达到自己的目的。
首先创建一个自定义的拦截器类,也是最核心的代码
  1. /**
  2. * @ProjectName: cdkj-framework
  3. * @Package: com.cdkjframework.core.spring.filter
  4. * @ClassName: FilterHandlerInterceptor
  5. * @Description: 拦截过滤
  6. * @Author: xiaLin
  7. * @Date: 2022/6/22 13:36
  8. * @Version: 1.0
  9. */
  10. public class FilterHandlerInterceptor implements HandlerInterceptor {
  11.   /**
  12.    * 日志日志
  13.    */
  14.   private LogUtils logUtils = LogUtils.getLogger(FilterHandlerInterceptor.class);
  15.   /**
  16.    * redis锁
  17.    */
  18.   private final RedisLettuceLock redisLettuceLock;
  19.   /**
  20.    * IP头部变量(可能通过Nginx代理后)
  21.    */
  22.   private static final String HEADER_IP = "X-Real-IP";
  23.   /**
  24.    * 锁IP请求URL地址KEY
  25.    */
  26.   private static final String LOCK_IP_URL_KEY = "lock_ip_";
  27.   /**
  28.    * IP请求URL地址时间
  29.    */
  30.   private static final String IP_URL_REQ_TIME = "ip_url_times_";
  31.   /**
  32.    * 极限时间
  33.    */
  34.   private static final long LIMIT_TIMES = 5;
  35.   /**
  36.    * IP锁定时间 秒
  37.    */
  38.   private static final int IP_LOCK_TIME = 60;
  39.   /**
  40.    * 构建函数
  41.    */
  42.   public FilterHandlerInterceptor(RedisLettuceLock redisLettuceLock) {
  43.     this.redisLettuceLock = redisLettuceLock;
  44.   }
  45.   /**
  46.    * 预处理
  47.    *
  48.    * @param request  请求
  49.    * @param response 响应
  50.    * @param o        参数
  51.    * @return 返回结果
  52.    * @throws Exception 异常信息
  53.    */
  54.   @Override
  55.   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
  56.     String ip = request.getHeader(HEADER_IP);
  57.     if (StringUtils.isNullAndSpaceOrEmpty(ip)) {
  58.       ip = request.getRemoteAddr();
  59.     }
  60.     logUtils.info("request 请求地址 Uri={},ip={}", request.getRequestURI(), ip);
  61.     if (ipIsLock(ip)) {
  62.       logUtils.info("ip访问被禁止={}", ip);
  63.       ResponseBuilder builder = ResponseBuilder.failBuilder("ip访问被禁止");
  64.       returnJson(response, builder);
  65.       return false;
  66.     }
  67.     if (!addRequest(ip, request.getRequestURI())) {
  68.       ResponseBuilder builder = ResponseBuilder.failBuilder("ip访问被禁止");
  69.       returnJson(response, builder);
  70.       return false;
  71.     }
  72.     return true;
  73.   }
  74.   @Override
  75.   public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
  76.   }
  77.   @Override
  78.   public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
  79.   }
  80.   /**
  81.    * IP 是否已锁
  82.    *
  83.    * @param ip IP 地址
  84.    * @return 返回是否成功
  85.    */
  86.   private Boolean ipIsLock(String ip) {
  87.     if (redisLettuceLock.lock(LOCK_IP_URL_KEY + ip)) {
  88.       return true;
  89.     }
  90.     return false;
  91.   }
  92.   /**
  93.    * 添加请求信息
  94.    *
  95.    * @param ip  IP 地址
  96.    * @param uri 请求路径
  97.    * @return 返回是否成功
  98.    */
  99.   private Boolean addRequest(String ip, String uri) {
  100.     String key = IP_URL_REQ_TIME + ip + uri;
  101.     if (RedisUtils.syncExists(key)) {
  102.       long time = RedisUtils.syncIncr(key, IntegerConsts.ONE);
  103.       if (time >= LIMIT_TIMES) {
  104.         redisLettuceLock.lock(LOCK_IP_URL_KEY + ip, IP_LOCK_TIME, ip);
  105.         return false;
  106.       }
  107.     } else {
  108.       redisLettuceLock.lock(key, (long) IntegerConsts.ONE, IntegerConsts.ONE);
  109.     }
  110.     return true;
  111.   }
  112.   /**
  113.    * 返回结果
  114.    *
  115.    * @param response 响应
  116.    * @param builder  返回结果
  117.    * @throws Exception 异常信息
  118.    */
  119.   private void returnJson(HttpServletResponse response, ResponseBuilder builder) throws Exception {
  120.     ResponseUtils.out(response, builder);
  121.   }
  122. }
复制代码
  最后将上面自定义的拦截器通过WebMvcConfigurer下的registry.addInterceptor添加一下,就生效了。
  1. /**
  2. * @ProjectName: cdkj-framework
  3. * @Package: com.cdkjframework.core.spring.filter
  4. * @ClassName: WebMvcFilterConfigurerAdapter
  5. * @Description: java类作用描述
  6. * @Author: xiaLin
  7. * @Date: 2022/6/22 13:37
  8. * @Version: 1.0
  9. */
  10. @RequiredArgsConstructor
  11. public class WebMvcFilterConfigurerAdapter implements WebMvcConfigurer {
  12.     /**
  13.      * redis锁
  14.      */
  15.     private final RedisLettuceLock redisLettuceLock;
  16.     /**
  17.      * 过虑句柄拦截器
  18.      *
  19.      * @return 返回拦截器
  20.      */
  21.     @Bean
  22.     private FilterHandlerInterceptor filterHandlerInterceptor() {
  23.         return new FilterHandlerInterceptor(redisLettuceLock);
  24.     }
  25.     /**
  26.      * 添加 拦截器
  27.      *
  28.      * @param registry 拦截器注册
  29.      */
  30.     @Override
  31.     public void addInterceptors(InterceptorRegistry registry) {
  32.         registry.addInterceptor(filterHandlerInterceptor()).addPathPatterns("/**");
  33.     }
  34. }
复制代码
  自己可以写一个for循环来测试改功能,这里就不具体详细介绍了。
文章中的工具类可参考:https://gitee.com/cdkjframework/common/tree/1.0.2/

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表