Spring boot拦截器实现IP黑名单的完整步骤

一·业务场景和需要实现的功能

以redis作为IP存储地址实现。

业务场景:针对秒杀活动或者常规电商业务场景等,防止恶意脚本不停的刷接口。

实现功能:写一个拦截器拦截掉黑名单IP,额外增加一个接口,将ip地址添加到redis中,并且返回redis中当前全部ip

二·Springboot中定义一个拦截器

@Order(0)
@Aspect
@Component
public class AopInterceptor {

  /**
   * 定义拦截器规则
   */
  @Pointcut("execution(* com.test.test.api.controller.test.test.*(..))")
  public void pointCut() {
  }

   /**
   * 拦截器具体实现
   *
   * @throws Throwable
   */
  @Around(value = "pointCut()")
  public Object around(ProceedingJoinPoint point) throws Throwable {
    try {

      HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
      //判断是否为黑名单用户
      String ip = getIpAddress(request);
      if (checkIpBlack(ip)) {
        //ip在黑名单中返回false
        //return false;
        DefaultResponse defaultResponse = new DefaultResponse();
        defaultResponse.setCode(-1);
        defaultResponse.setMessage("ip在黑名单中,拒绝访问.");
        SysLogHelper.log("IpBlackAopInterceptor", "当前请求ip" + ip, "ip在黑名单中,拒绝访问");
        return defaultResponse;
      } else {
        //ip不在黑名单中返回true
        SysLogHelper.log("IpBlackAopInterceptor", "当前请求ip" + ip, "ip正常,允许访问");
        return point.proceed();
      }

    } catch (Exception e) {
      e.printStackTrace();
      SysLogHelper.error("IpBlackAopInterceptor黑名单拦截异常:", ExceptionUtils.getMessage(e) + "详细" + ExceptionUtils.getStackTrace(e), null);
    }
    return point.getArgs();
  }

  //对比当前请求IP是否在黑名单中,注意(对比黑名单ip存放在redis中)
  public boolean checkIpBlack(String ip) throws Exception {
    IpBlackBody body = new IpBlackBody();
    body = cacheHelper.get("IpBlack:ips", IpBlackBody.class);
    if (body != null) {
      for (int i = 0; i < body.getIp().length; i++) {
        if (body.getIp()[i].equals(ip))
          return true;
      }
    }
    return false;
  }

}

三·获取请求主机IP地址

 public final static String getIpAddress(HttpServletRequest request)
      throws IOException {
    // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址

    String ip = request.getHeader("x-forwarded-for");

    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      if (ip == null || ip.length() == 0
          || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("Proxy-Client-IP");
      }
      if (ip == null || ip.length() == 0
          || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("WL-Proxy-Client-IP");
      }
      if (ip == null || ip.length() == 0
          || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("HTTP_CLIENT_IP");
      }
      if (ip == null || ip.length() == 0
          || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("HTTP_X_FORWARDED_FOR");
      }
      if (ip == null || ip.length() == 0
          || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getRemoteAddr();
      }
    } else if (ip.length() > 15) {
      String[] ips = ip.split(",");
      for (int index = 0; index < ips.length; index++) {
        String strIp = (String) ips[index];
        if (!("unknown".equalsIgnoreCase(strIp))) {
          ip = strIp;
          break;
        }
      }
    }

    return ip;
  }

四·扩展接口,实现将黑名单IP写入redis当中,并返回当前所有黑名单IP

@RestController
public class IpBlackController {

  @Autowired(required = false)
  private CacheHelper cacheHelper;

  @PostMapping("/testIpBlack")
  public IpBlackBody IpBlack(@RequestBody IpBlackBody ipBlackBody) throws Exception {

    IpBlackBody body = new IpBlackBody();
    body = cacheHelper.get("IpBlack:ips", IpBlackBody.class);

    if (body != null) {
      //拼接当前IP与redis中现有ip
      linkArray(body.getIp(), ipBlackBody.getIp());
      //将数据赋给body
      body.setIp(linkArray(body.getIp(), ipBlackBody.getIp()));
      //setex中第二个参数时间为S,根据业务场景相应调整,此处我设置为一天
      //将body中拼接后的ip地址数据写入redis中
      cacheHelper.setex("IpBlack:ips", 86400, body);

    } else {
      cacheHelper.setex("IpBlack:ips", 86400, ipBlackBody);
      body = cacheHelper.get("IpBlack:ips", IpBlackBody.class);
      return body;
    }
    return body;
  }

  //拼接两个String[]的方法
  public static String[] linkArray(String[] array1, String[] array2) {

    List<String> list = new ArrayList<>();
    if (array1 == null) {
      return array2;
    }
    if (array2 == null) {
      return array1;
    }
    for (int i = 0; i < array1.length; i++) {
      list.add(array1[i]);
    }
    for (int i = 0; i < array2.length; i++) {
      list.add(array2[i]);
    }
    String[] returnValue = new String[list.size()];
    for (int i = 0; i < list.size(); i++) {

      returnValue[i] = list.get(i);
    }
    return returnValue;
  }
}

总结:

首先根据需要拦截的controller拦截响应请求controller层,然后根据编写相关拦截器的具体实现,其中包含两部主要操作:

1.获取到远程请求主机的实际ip地址

2.对比当前ip是否在黑名单中(此次操作需要读取redis中的黑名单ip列表)

然后根据当前需求增加了一个redis接口,实现将需要封禁的IP地址增加到redis黑名单中并返回当前所有的黑名单IP地址。

至此:至此springboot通过拦截器实现拦截黑名单功能已经实现。

到此这篇关于Spring boot拦截器实现IP黑名单的文章就介绍到这了,更多相关Springboot拦截器IP黑名单内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • spring boot如何添加拦截器

    构建一个spring boot项目. 添加拦截器需要添加一个configuration @Configuration @ComponentScan(basePackageClasses = Application.class, useDefaultFilters = true) public class ServletContextConfig extends WebMvcConfigurationSupport { 为了方便扫描位置,我们可以写一个接口或者入口类Application放置于最外

  • 详解SpringBoot AOP 拦截器(Aspect注解方式)

    常用用于实现拦截的有:Filter.HandlerInterceptor.MethodInterceptor 第一种Filter属于Servlet提供的,后两者是spring提供的,HandlerInterceptor属于Spring MVC项目提供的,用来拦截请求,在MethodInterceptor之前执行. 实现一个HandlerInterceptor可以实现接口HandlerInterceptor,也可以继承HandlerInterceptorAdapter类,两种方法一样.这个不在本文

  • SpringBoot定义过滤器、监听器、拦截器的方法

    一.自定义过滤器 创建一个过滤器,实现javax.servlet.Filter接口,并重写其中的init.doFilter.destory方法. package com.example.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.Se

  • spring boot拦截器实现IP黑名单实例代码

    前言 最近一直在搞 Hexo+GithubPage 搭建个人博客,所以没怎么进行 SpringBoot 的学习.所以今天就将上次的"?秒防刷新"进行了一番修改.上次是采用注解加拦截器(@Aspect)来实现功能的.但是,如果需求是一个全局的拦截器对于大部分URL都进行拦截的话,自己一个个加显然是不可能的.而且上次的拦截器对于Controller的参数有所要求,在实际他人引用总是显得不方便.所以,这次使用了继承HandlerInterceptor来实现拦截器. 功能需求 对于项目中某类U

  • SpringBoot拦截器的使用小结

    总结一下SpringBoot下拦截器的使用,步骤很简单: 1.自定义自己的拦截类,拦截类需要继承HandlerInterceptor接口并实现这个接口的方法. @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { //方法调用前执行 return true;//返回

  • Spring boot拦截器实现IP黑名单的完整步骤

    一·业务场景和需要实现的功能 以redis作为IP存储地址实现. 业务场景:针对秒杀活动或者常规电商业务场景等,防止恶意脚本不停的刷接口. 实现功能:写一个拦截器拦截掉黑名单IP,额外增加一个接口,将ip地址添加到redis中,并且返回redis中当前全部ip 二·Springboot中定义一个拦截器 @Order(0) @Aspect @Component public class AopInterceptor { /** * 定义拦截器规则 */ @Pointcut("execution(*

  • Spring Boot拦截器和过滤器实例解析

    这篇文章主要介绍了Spring Boot拦截器和过滤器实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.拦截器与过滤器 在讲Spring boot之前,我们先了解一下过滤器和拦截器.这两者在功能方面很类似,但是在具体技术实现方面,差距还是比较大的.在分析两者的区别之前,我们先理解一下AOP的概念,AOP不是一种具体的技术,而是一种编程思想.在面向对象编程的过程中,我们很容易通过继承.多态来解决纵向扩展. 但是对于横向的功能,比如,在所

  • spring boot拦截器的使用场景示例详解

    前言 在用户登陆之后,我们一般会把用户登陆的状态和相关信息进行存储,把对应的token返回到客户端进行存储,下次请求过来时,系统可以通过token拿到当前这个用户的相关信息,这是授权通常的作法,而有时一些业务里,你存储的用户信息不是全局的,可能只是某几个接口会用户某些信息,而你把它存储起来就不是很合理:并且一些隐私信息持久化到redis也不合理,这时就需要统一对这种接口的请求做一起处理了. 拦截器HandlerInterceptor 我们可以去实现这个HandlerInterceptor接口,它

  • spring boot拦截器注入不了java bean的原因

    一.如何实现拦截器 在Spring Boot项目中,拦截器经常被用来做登陆验证,日志记录等操作.拦截器是Spring提供的,所以可以将拦截器注成bean,由IOC容器来管理.实现拦截器的方式很简单,主要由以下两个步骤: 自定义拦截器类实现HandlerInterceptor接口 自定义WebMvc配置类实现WebMvcConfigurer接口,添加自定义拦截器类 简要实现代码如下: 自定义拦截器 LoginInterceptor: public class LoginInterceptor im

  • SpringMVC通过拦截器实现IP黑名单

    以前没有遇到这个需要,后面在网上找了很久,参考了很多文档给出的方案. 1.配置拦截器 这里使用全局拦截: <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.nps.base.filter.LoginInterceptor"></bean> </mvc:interceptor> </

  • Spring Boot拦截器实现步骤及测试实例

    第一步,定义拦截器: package com.zl.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public

  • spring boot+vue实现JSAPI微信支付的完整步骤

    目录 微信支付 微信支付前的准备 后台开发 vue前端 总结 微信支付 最近公司要在微信公众号上做一个活动预报名,活动的门票等需要在微信中支付. 微信支付前的准备 微信支付需要一个微信支付商务号(https://pay.weixin.qq.com/index.php/apply/applyment_home/guide_normal),请自行去商务平台申请.商务号申请完后,需要在 “微信公众号平台–>微信支付” 中接入.接入成功后还需要在 “微信公众号平台–>设置–>公众号设置–>

  • 在Spring Boot中加载XML配置的完整步骤

    开篇 在SpringBoot中我们通常都是基于注解来开发的,实话说其实这个功能比较鸡肋,但是,SpringBoot中还是能做到的.所以用不用是一回事,会不会又是另外一回事. 涛锅锅在个人能力能掌握的范围之内,一般是会得越多越好,都是细小的积累,发生质的改变,所以今天和小伙伴们一起分享一下. 实践 1.首先我们新建一个SpringBoot Project ,工程名为 xml 2.添加web依赖,点击Finish完成构建 3.我们新建一个类 SayHello 不做任何配置 package org.t

  • Spring Boot利用Docker快速部署项目的完整步骤

    1.简介 建议阅读本文最好对Dokcer有一些了解 首先我们先了解一下Docker是什么 Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口.它是目前最流行的 Linux 容器解决方案. Docker 将应用程序与该程序的依赖,打包在一个文件里面.运行这个文件,就会生成一个虚拟容器.程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样.有了 Docker,就不用担心环境问题. 总体来说,Docker 的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器.

随机推荐