本文目录导读:

在Java中实现黑白名单功能,通常用于权限控制、IP访问限制、接口防刷、数据过滤等场景。
根据你的具体场景(是配置IP、用户ID、还是特定词条),配置方式会有所不同,以下是几个最常见的Java黑白名单配置案例及方案:
基于IP地址的黑白名单(后端最常用)
通常用于过滤恶意请求或限制内部访问,常用存储介质:配置文件(简单)或 Redis(动态)。
配置文件方式(适合规则少、不频繁变动的场景)
第一步:配置文件(application.yml 或 application.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 | 快速开发、静态配置 |
总结建议
- 首选动态配置: 生产环境尽量避免修改代码重启,使用 Redis 或 数据库 存储规则。
- 双名单逻辑: 通常先判断黑名单(快速拒绝),再判断白名单(精确放行),最后根据默认策略(允许/拒绝)处理未匹配的请求。
- 注意性能: 如果黑白名单数据量很大(如百万级IP),不要使用
List.contains(),改用 HashSet 或 Redis Set 的 O(1) 查询。
你需要针对哪种具体的对象(IP、用户、关键词)做黑白名单?我可以给出更针对性的代码示例。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播