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是否存在。

该方法参考博客:https://blog.csdn.net/gy99csdn/article/details/114336738

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配置,类似热更新,可在运维平台手动操作黑名单

不足:仍需手动操作。

分布式

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

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

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

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

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

参考:

https://blog.csdn.net/qq_25620555/article/details/84262577

https://blog.csdn.net/gy99csdn/article/details/114336738

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

csdn.net/qq_25620555/article/details/84262577

https://blog.csdn.net/gy99csdn/article/details/114336738

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

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

  • 29
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程就是n踢r

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值