首页 > 编程语言 >java——ip黑名单设计方案(大全+实战)

java——ip黑名单设计方案(大全+实战)

时间:2024-01-29 22:04:23浏览次数:30  
标签:拦截器 java 自定义 ip 黑名单 ips

java——ip黑名单设计方案(大全+实战)

大家好,今天来设计一个ip黑名单功能。即封禁一些类似ddos的非法ip

环境:springboot+jdk11

本文源码地址:https://gitee.com/xue-shangren/blog-src/tree/master/java-blacklist-design

自定义拦截器

思路:将黑名单ip存入一个txt文件中(置于resources下),用一个bean去加载文件内容,并存入一个Set中。

然后自定义拦截器,去对ip进行检查。

实例代码

1.先创建一个blackList.txt文件,存入黑名单ip,如图所示。

image-20240128214626155

2.然后创建一个IpService,在构造函数中去加载这个txt文件,并写入Set中。

image-20240128214824332

image-20240128214808665

并向外提供Set的访问方式,让装载IpService的其他类调用,检查ip。

image-20240128214916707

3.自定义黑名单ip拦截器,用于第一层处理非法ip。记录日志

image-20240128215005890

在该拦截器中,我们从request中获取到真实ip,并进行检查。若Set中存在该ip则拦截,否则通过。

4.注册自定义拦截器

image-20240128215243126

测试结果

image-20240128215259766

image-20240128215145635

image-20240128215208562

自定义过滤器

过滤器依赖于Servlet容器,并且不能获取IOC容器的bean,所以springboot一般不用自定义filter去搞这种,因为不能注入service等@bean。很难受

Q:为什么过滤器不能获取IOC容器的bean吗,而拦截器可以

A:过滤器由Servlet容器管理(Tomcat,Netty),它的初始化在spring之前。而拦截器则是在controller之前,在spring初始化后初始化。

上有政策,下有对策。过滤器也可以实现黑名单ip

这里提供一种思路,而不是说它的可行性。

思路:由于过滤器可以处理Servlet,所以可以使用ServletContext去存一个key-value,也就是黑名单列表。

在请求到来的时候,用监听器监听该Servlet,并将文件加载并存入该Servlet的ServletContext中。然后用filter去手动检查该ip是否存在。

jmx注册MBean注册到JMX,黑名单ip保留为一个set,监控程序去动态添加

结合spring sercuity

黑名单ip保存到yml中

思路:将黑名单ip保存到yml文件中,通过@ConfigurationProperties注解去获取到blackips。

然后在SecurityConfig中根据request进行Match。

image-20240128225700712

image-20240128225817210

如上所示:registry根据request进行匹配,当匹配黑名单ip时,就将其拦截,否则放行。

缺点很明显:yml文件是项目写死的。不能动态实时更新这些黑名单ip,只能重启应用。一般不采取

jmx动态配置

JMX(java management Extensions),是一个jdk自带的java平台监控和管理接口。

它提供了一种获取java程序的内存,cpu,线程状态,jvm参数等运行信息的规范(就像servlet标准对应一个个请求)

其他运维程序通过实现jmx接口,即可它获取正在运行的java程序的内存,cpu,线程状态,jvm参数等信息

如jconsole,Zabbix等运维工具

jmx将所有被管理的资源都称为MBean(Managed Bean),这些MBean全部由MBeanServer管理,如果要访问MBean,可以通过MBeanServer对外提供的访问接口,例如通过RMI或HTTP访问。

jmx内置在javase标准库

这里我们通过编写一个Mbean并通过spring注册到jmx中,然后通过jconsole动态调整ip黑名单

1.注册Mbean

/**
 * @Author:xsr
 * @Date:2024/1/29 18:49
 * 黑名单ip服务类 Mbean
 */
@Component
@ManagedResource(objectName = "sample:name=blacklist",description = "Blacklist of IP addresses")
public class BlacklistMBean {
    private Set<String> ips = new HashSet<>();
    @ManagedAttribute(description = "Get IP addresses in blacklist")
    public String[] getBlacklist() {
        return ips.toArray(String[]::new);
    }

    @ManagedOperation
    @ManagedOperationParameter(name = "ip", description = "Target IP address that will be added to blacklist")
    public void addBlacklist(String ip) {
        ips.add(ip);
    }

    @ManagedOperation
    @ManagedOperationParameter(name = "ip", description = "Target IP address that will be removed from blacklist")
    public void removeBlacklist(String ip) {
        ips.remove(ip);
    }

    /**
     * 该方法不被MbeanServer管理
     * @param ip
     * @return
     */
    public boolean shouldBlock(String ip) {
        return ips.contains(ip);
    }

}

然后重启服务,通过jconsole查看注册的属性和操作。

image-20240129190736628

然后我们可以jconsole的界面,向addBlacklist和removeBlacklist传参,并手动调用方法。

这个set集合ips就会在运行中添加/删除你要操作的ip。

image-20240129191435894

该方案好处:胜于重启项目来更新yml配置,类似热更新,可在运维平台手动操作黑名单

不足:仍需手动操作。

分布式

在分布式架构中,可以使用统一网关鉴权,也可以使用中心化黑名单存储,后者需要注意

各节点同步:即当某个节点更新黑名单时,其他节点能够及时获取最新的黑名单信息。

持久化存储:可以考虑使用持久化存储(数据库)来确保黑名单信息在服务重启后不会丢失

各节点的缓存机制:各节点上可以使用缓存机制来存储最近使用过的黑名单信息,以减少对中心化服务的频繁访问

异步操作中心黑名单:中心化服务在更新黑名单时可以通过消息队列通知各个节点进行异步更新,而不是同步阻塞业务

参考:

chatgpt关键词:java黑名单设计;spring security黑名单设计;ConfigurationProperties代替txt文件的黑名单设计

https://www.liaoxuefeng.com/wiki/1252599548343744/1282385687609378

标签:拦截器,java,自定义,ip,黑名单,ips
From: https://blog.51cto.com/u_16286631/9472600

相关文章

  • java 判断当前时间是否可以执行
    判断时间privatebooleancanTheTimeExecute(){try{if(StringUtils.isEmpty(containerStockSyncTime)){log.info("[handleContainerStockSyncTask]-executetimeisempty。");returnfalse;}//配置中心按照分钟......
  • java8线上GC问题排查
    问题线上长时间fullGc项目输出了对应的gc日志,启动参数里增加了对应启动参数-verbose:gc-Xloggc:/logs/java_gc.log-XX:+PrintGCDateStamps-XX:+PrintGCApplicationStoppedTime-XX:+PrintGCApplicationConcurrentTime-XX:+PrintHeapAtGC-XX:HeapDumpPath=/logs/java_he......
  • CF1925D Good Trip 题解
    考虑分别计算\(p\)和\(q\)。按照期望的定义,\(q\)应该等于方案的总数,也就是\(s^k\),其中\(s\)表示一共有多少个不同的组。考虑如何求\(p\),我们先只计算第\(i\)组对\(p\)的贡献。如果第\(i\)组一共被选了\(1\)次,那么贡献为:\[g=f_i\timesC_{k}^{1}\times(s-1)^{......
  • Java编程学习(intellij idea)
    打开IntelliJIDEA新建Project新建Module新建Package输入Package名,enter新建JavaClass在Class中编程......
  • Java删除及下载
    卸载JDK删除JAVA的安装目录删除JAVA_HOME删除path下关于JAVA的目录命令行窗口java-version安装JDK搜索JDK8,找到下载地址同意协议下载电脑对应版本双击安装JDK记住安装路径D:\Environment\java\jdk1.8\配置环境变量我的电脑-->右键-->属性点击高级系统设置在系......
  • 初识Jjava --数组
    Day6publicstaticvoidmain(String[]args){int[]nums;//定义一个数组nums=newint[10];nums[0]=1;nums[1]=2;nums[2]=3;nums[3]=4;nums[4]=5;nums[5]=6;nums[6]=7;nums[7]=8;......
  • 在内网(不通公网)的情况下,使用pip安装python依赖包
    1.施工服务器后端部署一:准备一台环境与内网虚拟机相同的可以连接外网的虚拟机,python版本,操作系统版本保持一致二:在可以链接外网的机器上使用pip将依赖包的whl文件(也有可能是tar.gz或者tar格式,不过不影响后续使用)#将依赖下载到本地的某个文件中root@iZ8v2rbZ:/sdwork/pyyl#......
  • Apipost中API如何调用本地文件
    近期版本更新中Apipost推出插件管理,可以直接在预、后执行脚本中调用本地的脚本文件导入脚本在「系统设置」—「插件管理」中打开目录将要执行的脚本文件拖入到文件夹下 执行脚本需要获取请求参数:constrequestData=request.request_bodys;在预、后执行脚本输入框中输入......
  • 服务器IP地址的分类
    1、A类IP地址:一个A类IP地址由1字节的网络地址和3字节主机地址组成,网络地址的最高位必须是“0”,地址范围从1.0.0.0到126.0.0.0。可用的A类网络有126个,每个网络能容纳1亿多个主机。2、B类IP地址:一个B类IP地址由2个字节的网络地址和2个字节的主机地址组成,网络地址的最高位必须是......
  • java用多线程批次查询大量数据(Callable返回数据)方式
    我看到有的数据库是一万条数据和八万条数据还有十几万条,几百万的数据,然后我就想拿这些数据测试一下,发现如果用java和数据库查询就连一万多条的数据查询出来就要10s左右,感觉太慢了。然后网上都说各种加索引,加索引貌似是有查询条件时在某个字段加索引比较快一些,但是毕竟是人家的库不......