Java黑白名单案例怎么配置

wen java案例 29

本文目录导读:

Java黑白名单案例怎么配置

  1. 方案一:基于IP地址的黑白名单(后端最常用)
  2. 方案二:基于用户ID/角色的黑白名单(权限管理)
  3. 方案三:基于敏感词的黑白名单(内容过滤)
  4. 如何选择配置方案?
  5. 总结建议

在Java中实现黑白名单功能,通常用于权限控制IP访问限制接口防刷数据过滤等场景。

根据你的具体场景(是配置IP、用户ID、还是特定词条),配置方式会有所不同,以下是几个最常见的Java黑白名单配置案例及方案:

基于IP地址的黑白名单(后端最常用)

通常用于过滤恶意请求或限制内部访问,常用存储介质:配置文件(简单)或 Redis(动态)。

配置文件方式(适合规则少、不频繁变动的场景)

第一步:配置文件(application.ymlapplication.properties

# application.properties
# 黑名单IP,多个用逗号分隔
blacklist.ips=192.168.1.100,10.0.0.50
# 白名单IP(如果启用白名单,只有这些IP能访问)
whitelist.ips=192.168.1.1,127.0.0.1
# 启用模式:black(黑名单模式,禁止黑名单访问) / white(白名单模式,仅允许白名单访问)
access.mode=black

第二步:Java 配置加载类

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@ConfigurationProperties(prefix = "access")
public class AccessConfig {
    private String mode;
    private List<String> blacklistIps;
    private List<String> whitelistIps;
    // getter 和 setter 省略...
}

第二步:过滤器实现

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@Component
public class IpFilter implements Filter {
    private final AccessConfig accessConfig;
    public IpFilter(AccessConfig accessConfig) {
        this.accessConfig = accessConfig;
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        String ip = req.getRemoteAddr(); // 获取客户端IP
        boolean isBlocked = false;
        if ("black".equals(accessConfig.getMode())) {
            // 黑名单模式:如果IP在黑名单里,禁止访问
            isBlocked = accessConfig.getBlacklistIps().contains(ip);
        } else if ("white".equals(accessConfig.getMode())) {
            // 白名单模式:如果IP不在白名单里,禁止访问
            isBlocked = !accessConfig.getWhitelistIps().contains(ip);
        }
        if (isBlocked) {
            res.setStatus(403);
            res.getWriter().write("Access Denied");
            return;
        }
        chain.doFilter(request, response);
    }
}

动态配置方式(适合规则频繁变化、需要热加载)

使用 Redis Set 结构,结合 AOP拦截器

import redis.clients.jedis.Jedis;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
public class IpWhitelistInterceptor implements HandlerInterceptor {
    @Autowired
    private StringRedisTemplate redisTemplate; // 假设引入了Spring Data Redis
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String ip = request.getRemoteAddr();
        String whiteListKey = "ip:whitelist";
        String blackListKey = "ip:blacklist";
        // 1. 先检查黑名单(如果有)
        Boolean isBlack = redisTemplate.opsForSet().isMember(blackListKey, ip);
        if (Boolean.TRUE.equals(isBlack)) {
            response.setStatus(403); // Access Forbidden
            return false;
        }
        // 2. 检查白名单
        Boolean isWhite = redisTemplate.opsForSet().isMember(whiteListKey, ip);
        if (Boolean.TRUE.equals(isWhite)) {
            return true; // 放行
        }
        // 3. 既不在黑名单也不在白名单,可以根据策略决定(允许/拒绝)
        // 拒绝所有未在白名单的IP
        response.setStatus(403);
        return false;
    }
}

优点: 运维可以直接通过 redis-cli sadd ip:whitelist 192.168.1.200 添加白名单,无需重启服务。


基于用户ID/角色的黑白名单(权限管理)

常用于封禁用户或VIP白名单。

配置方式(数据表):

设计一张数据库表 user_acl

CREATE TABLE user_acl (
    id BIGINT PRIMARY KEY,
    user_id BIGINT NOT NULL,
    type VARCHAR(10) NOT NULL COMMENT 'BLACK 或 WHITE',
    reason VARCHAR(255),
    created_at TIMESTAMP
);

Java 实现(以注解 + AOP 为例):

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckBlacklist {
    String value() default "user";
}
@Aspect
@Component
public class BlacklistAspect {
    @Autowired
    private UserAclService userAclService;
    @Around("@annotation(checkBlacklist)")
    public Object around(ProceedingJoinPoint joinPoint, CheckBlacklist checkBlacklist) {
        Long userId = getCurrentUser(); // 从Token或Session获取
        boolean isBlack = userAclService.isUserBlacklisted(userId);
        if (isBlack) {
            throw new BusinessException("用户已被列入黑名单,无法操作");
        }
        return joinPoint.proceed();
    }
}

使用:

@PostMapping("/transfer")
@CheckBlacklist // 需要检查黑名单
public Result transfer(@RequestBody TransferReq req) { ... }

基于敏感词的黑白名单(内容过滤)

常用于评论系统、用户昵称过滤。

配置方式(文件或数据库):

第一步:初始化敏感词库(启动时加载到内存)

@Component
public class SensitiveWordFilter {
    // 黑名单敏感词
    private Set<String> blackWords = new HashSet<>(Arrays.asList("垃圾", "广告", "骗子"));
    // 白名单例外词(广告虽敏感,但“广告部”是正常词)
    private Set<String> whiteWords = new HashSet<>(Arrays.asList("广告部", "广告公司")); 
    public boolean containsSensitiveWord(String text) {
        for (String black : blackWords) {
            if (text.contains(black)) {
                // 检查是否命中白名单
                boolean isException = whiteWords.stream().anyMatch(text::contains);
                if (!isException) {
                    return true; // 检测到黑名单词且不在白名单例外中
                }
            }
        }
        return false;
    }
}

注意: 实际项目中建议使用 Trie树(前缀树)DFA算法 提高效率,上面仅为演示逻辑。


如何选择配置方案?

场景 推荐配置方式 特点
API 访问控制(IP/API Key) Redis + 拦截器 动态更新、高性能、分布式
权限白名单(用户/角色) 数据库 + AOP 持久化、可管理、适合复杂业务
敏感词过滤 本地缓存(如Caffeine) + 文件 低延迟、不依赖外部服务
简单业务测试 application.yml + Filter 快速开发、静态配置

总结建议

  1. 首选动态配置: 生产环境尽量避免修改代码重启,使用 Redis数据库 存储规则。
  2. 双名单逻辑: 通常先判断黑名单(快速拒绝),再判断白名单(精确放行),最后根据默认策略(允许/拒绝)处理未匹配的请求。
  3. 注意性能: 如果黑白名单数据量很大(如百万级IP),不要使用 List.contains(),改用 HashSetRedis Set 的 O(1) 查询。

你需要针对哪种具体的对象(IP、用户、关键词)做黑白名单?我可以给出更针对性的代码示例。

抱歉,评论功能暂时关闭!