黑白名单方案

通用黑白名单方案

背景

设计一套灵活的黑白名单机制,要求无需修改代码即可修改黑白名单逻辑的切换。使用场景如下,比如原先一个新功能上线,我们期望给部分企业使用;等功能成熟后,我们一般会开放给所有的企业一起使用,但是好巧不巧,一家企业不愿意使用这个功能。我们不可能给每一个企业配置白名单。这样,我们就需要一个黑名单功能,即实现单独给不愿意使用新功能的企业单独配置一个名单。
为了不修改代码,我们只需要修改名单类型,配置相关名单的企业就好了。

方案设计

+----------------+        +-----------------+
|  Feature Flag  |        |  Configuration  |
|   Management   |        |     Storage     |
|     System     |        | (e.g., JSON,    |
+-------+--------+        |  Database, etc.) |
        |                 +--------+---------+
        |                          |
        |                          |
        |      +------------+      |
        +----->+  Blacklist +<-----+
               +------------+
                     ^
                     |
                     v
               +------------+
               |  Whitelist  |
               +------------+
                     ^
                     |
                     v
               +------------+
               | Enterprise |
               |  Service   |

需要新建两张表:

  • 开关表设计:表明自己是白名单、还是黑名单,以及对应的开关状态。
  • 控制关联表则记录关联的企业ID。

方案可行性评估:

提出的黑白名单机制在设计上是可行的,可以通过数据库表来控制名单的逻辑和状态。通过这种设计,可以在不修改代码的情况下,通过更新数据库表来切换黑白名单的逻辑和修改名单内容。这种方法可以提供灵活的配置管理,并且可以即时生效,符合要求。

数据库表设计:

我们需要两张表,一张是名单模式开关表(list_switch),另一张是名单关联表(list_association)。

  1. 名单模式开关表(list_switch):用来记录当前名单模式是黑名单还是白名单,以及开关状态。
CREATE TABLE `list_switch` (
  `id` INT AUTO_INCREMENT PRIMARY KEY,
  `list_type` ENUM('BLACKLIST', 'WHITELIST') NOT NULL,
  `is_active` BOOLEAN NOT NULL DEFAULT TRUE,
  `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
  1. 名单关联表(list_association):记录关联的企业ID,与名单模式开关表关联。
CREATE TABLE `list_association` (
  `id` INT AUTO_INCREMENT PRIMARY KEY,
  `enterprise_id` INT NOT NULL,
  `list_switch_id` INT NOT NULL,
  FOREIGN KEY (`list_switch_id`) REFERENCES `list_switch`(`id`)
);

示例代码:
以下是一个简单的 Spring Boot 服务层示例,演示了如何根据数据库表中的配置来决定是否允许某个企业ID执行操作。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.jdbc.core.JdbcTemplate;

@Service
public class ListService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public boolean isAllowed(int enterpriseId) {
        // 查询当前名单模式和状态
        String listSwitchSql = "SELECT list_type, is_active FROM list_switch WHERE is_active = TRUE LIMIT 1";
        Map<String, Object> listSwitch = jdbcTemplate.queryForMap(listSwitchSql);

        String listType = (String) listSwitch.get("list_type");
        boolean isActive = (Boolean) listSwitch.get("is_active");

        if (!isActive) {
            // 如果名单模式未激活,允许所有操作
            return true;
        }

        // 查询企业ID是否在名单关联表中
        String listAssociationSql = "SELECT COUNT(1) FROM list_association WHERE enterprise_id = ?";
        int count = jdbcTemplate.queryForObject(listAssociationSql, new Object[]{enterpriseId}, Integer.class);

        if ("WHITELIST".equals(listType)) {
            // 如果是白名单模式,只有在名单中的企业ID才允许操作
            return count > 0;
        } else if ("BLACKLIST".equals(listType)) {
            // 如果是黑名单模式,名单中的企业ID不允许操作
            return count == 0;
        }

        // 默认允许操作
        return true;
    }
}

在这个示例中,isAllowed 方法首先检查名单模式是否激活,并获取当前的名单类型。然后,它查询关联表以确定企业ID是否在名单中。根据名单类型(黑名单或白名单),方法返回是否允许企业ID执行操作。

这个示例提供了一个基础的实现,但在实际应用中,你可能需要添加更多的逻辑来处理并发更新、缓存名单状态以提高性能、提供管理接口来更新名单等。此外,为了保证数据的一致性和可靠性,你可能还需要在数据库操作中使用事务管理。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

子涵先生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值