本文目录导读:

实现Java白名单校验通常有几种常见方案,我为你整理了一个完整的案例,包含从简单到企业级的实现方式。
基础实现方案
使用Set集合(最简单)
import java.util.HashSet;
import java.util.Set;
public class SimpleWhitelistValidator {
private Set<String> whitelist;
public SimpleWhitelistValidator() {
// 初始化白名单
whitelist = new HashSet<>();
whitelist.add("192.168.1.1");
whitelist.add("192.168.1.100");
whitelist.add("10.0.0.1");
}
public boolean isValid(String ip) {
return whitelist.contains(ip);
}
// 使用示例
public static void main(String[] args) {
SimpleWhitelistValidator validator = new SimpleWhitelistValidator();
String testIp = "192.168.1.1";
if (validator.isValid(testIp)) {
System.out.println(testIp + " 在白名单中,允许访问");
} else {
System.out.println(testIp + " 不在白名单中,拒绝访问");
}
}
}
支持通配符匹配
import java.util.ArrayList;
import java.util.List;
public class PatternWhitelistValidator {
private List<String> whitelistPatterns;
public PatternWhitelistValidator() {
whitelistPatterns = new ArrayList<>();
// 支持通配符 * 和 ?
whitelistPatterns.add("192.168.1.*"); // 匹配所有192.168.1.x
whitelistPatterns.add("10.0.?.1"); // 匹配10.0.x.1
whitelistPatterns.add("172.16.0.1-100"); // 匹配172.16.0.1到172.16.0.100
}
public boolean isValid(String ip) {
for (String pattern : whitelistPatterns) {
if (matchPattern(ip, pattern)) {
return true;
}
}
return false;
}
private boolean matchPattern(String ip, String pattern) {
// 处理范围匹配
if (pattern.contains("-")) {
return matchRange(ip, pattern);
}
// 处理通配符匹配
String regex = pattern
.replace(".", "\\.")
.replace("*", "[0-9]{1,3}")
.replace("?", "[0-9]");
return ip.matches(regex);
}
private boolean matchRange(String ip, String pattern) {
String[] parts = pattern.split("-");
if (parts.length != 2) return false;
String baseIp = parts[0].substring(0, parts[0].lastIndexOf(".") + 1);
int start = Integer.parseInt(parts[0].substring(parts[0].lastIndexOf(".") + 1));
int end = Integer.parseInt(parts[1]);
String ipBase = ip.substring(0, ip.lastIndexOf(".") + 1);
if (!ipBase.equals(baseIp)) return false;
int ipLast = Integer.parseInt(ip.substring(ip.lastIndexOf(".") + 1));
return ipLast >= start && ipLast <= end;
}
}
企业级实现方案
使用注解+AOP实现
// 1. 自定义注解
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface WhitelistCheck {
String[] value() default {};
String param() default "ip";
}
// 2. 白名单配置类
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "whitelist")
public class WhitelistConfig {
private List<String> ips = new ArrayList<>();
private List<String> patterns = new ArrayList<>();
// getters and setters
public List<String> getIps() { return ips; }
public void setIps(List<String> ips) { this.ips = ips; }
public List<String> getPatterns() { return patterns; }
public void setPatterns(List<String> patterns) { this.patterns = patterns; }
}
// 3. AOP切面实现
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
@Aspect
@Component
public class WhitelistAspect {
@Autowired
private WhitelistConfig whitelistConfig;
@Around("@annotation(whitelistCheck)")
public Object checkWhitelist(ProceedingJoinPoint joinPoint, WhitelistCheck whitelistCheck) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
String clientIp = getClientIp(request);
// 获取方法参数中的IP(如果存在)
String paramIp = getParamIp(joinPoint, whitelistCheck.param());
String ipToCheck = paramIp != null ? paramIp : clientIp;
// 检查白名单
if (!isWhitelisted(ipToCheck, whitelistCheck.value())) {
throw new SecurityException("IP " + ipToCheck + " 不在白名单中");
}
return joinPoint.proceed();
}
private boolean isWhitelisted(String ip, String[] annotationWhitelist) {
// 先检查注解中的白名单
if (annotationWhitelist.length > 0) {
for (String allowed : annotationWhitelist) {
if (allowed.equals(ip)) return true;
}
}
// 再检查配置文件中的白名单
if (whitelistConfig.getIps().contains(ip)) return true;
// 检查模式匹配
for (String pattern : whitelistConfig.getPatterns()) {
if (ip.matches(patternToRegex(pattern))) return true;
}
return false;
}
private String getClientIp(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
private String getParamIp(ProceedingJoinPoint joinPoint, String paramName) {
Object[] args = joinPoint.getArgs();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
String[] paramNames = signature.getParameterNames();
for (int i = 0; i < paramNames.length; i++) {
if (paramNames[i].equals(paramName)) {
return (String) args[i];
}
}
return null;
}
private String patternToRegex(String pattern) {
return "^" + pattern
.replace(".", "\\.")
.replace("*", "[0-9]{1,3}")
.replace("?", "[0-9]") + "$";
}
}
// 4. 使用示例
@RestController
public class ApiController {
@GetMapping("/api/sensitive")
@WhitelistCheck(value = {"192.168.1.1"}, param = "ip")
public String sensitiveApi(@RequestParam(required = false) String ip) {
return "敏感数据";
}
@GetMapping("/api/admin")
@WhitelistCheck
public String adminApi() {
return "管理接口";
}
}
基于数据库的动态白名单
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import javax.persistence.*;
// 1. 实体类
@Entity
@Table(name = "whitelist")
public class WhitelistEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String ip;
@Column(name = "ip_type")
private String type; // SINGLE, RANGE, PATTERN
@Column(name = "ip_range_start")
private String rangeStart;
@Column(name = "ip_range_end")
private String rangeEnd;
private String description;
@Column(name = "is_active")
private Boolean active = true;
// getters and setters...
}
// 2. 仓库接口
public interface WhitelistRepository extends JpaRepository<WhitelistEntity, Long> {
@Query("SELECT w FROM WhitelistEntity w WHERE w.active = true AND w.ip = ?1")
List<WhitelistEntity> findByIp(String ip);
@Query("SELECT w FROM WhitelistEntity w WHERE w.active = true AND w.type = ?1")
List<WhitelistEntity> findByType(String type);
}
// 3. 缓存的服务类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class DynamicWhitelistService {
@Autowired
private WhitelistRepository repository;
@Cacheable(value = "whitelist", key = "#ip")
public boolean checkIp(String ip) {
// 1. 精确匹配
List<WhitelistEntity> exactMatches = repository.findByIp(ip);
if (!exactMatches.isEmpty()) return true;
// 2. 范围匹配
List<WhitelistEntity> rangeRules = repository.findByType("RANGE");
for (WhitelistEntity rule : rangeRules) {
if (isInRange(ip, rule.getRangeStart(), rule.getRangeEnd())) {
return true;
}
}
// 3. 模式匹配
List<WhitelistEntity> patternRules = repository.findByType("PATTERN");
for (WhitelistEntity rule : patternRules) {
if (ip.matches(patternToRegex(rule.getIp()))) {
return true;
}
}
return false;
}
private boolean isInRange(String ip, String start, String end) {
long ipLong = ipToLong(ip);
return ipLong >= ipToLong(start) && ipLong <= ipToLong(end);
}
private long ipToLong(String ipAddress) {
String[] ipArray = ipAddress.split("\\.");
long result = 0;
for (int i = 0; i < ipArray.length; i++) {
int power = 3 - i;
result |= (Long.parseLong(ipArray[i]) << (power * 8));
}
return result;
}
}
性能优化方案
使用布隆过滤器(适用于海量白名单)
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import javax.annotation.PostConstruct;
import java.nio.charset.Charset;
public class BloomFilterWhitelist {
private BloomFilter<String> bloomFilter;
@PostConstruct
public void init() {
// 创建布隆过滤器,预计10000个元素,误报率0.01
bloomFilter = BloomFilter.create(
Funnels.stringFunnel(Charset.defaultCharset()),
10000,
0.01
);
// 加载白名单
loadWhitelist();
}
private void loadWhitelist() {
// 从配置文件或数据库加载白名单IP
List<String> whitelistIps = getWhitelistIps();
for (String ip : whitelistIps) {
bloomFilter.put(ip);
}
}
public boolean mightContain(String ip) {
// 布隆过滤器可能误判,需要二次确认
if (bloomFilter.mightContain(ip)) {
return exactCheck(ip); // 二次精确检查
}
return false;
}
private boolean exactCheck(String ip) {
// 在白名单中做精确查找
return true; // 简化实现
}
}
application.yml配置示例
whitelist:
ips:
- 192.168.1.1
- 10.0.0.1
- 172.16.0.1
patterns:
- 192.168.1.*
- 10.0.*.1
最佳实践建议
- 缓存机制:使用Redis或本地缓存减少数据库查询
- 动态更新:支持运行时动态添加/移除白名单
- 日志记录:记录所有白名单校验的请求
- 性能监控:监控校验耗时,优化热点路径
- 降级策略:当白名单服务不可用时,有合理的降级方案
选择哪种方案取决于你的具体需求:
- 小型应用:使用Set或List
- 中型应用:使用注解+AOP
- 大型应用:使用数据库+缓存+布隆过滤器
需要根据你的实际场景选择合适的实现方式。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播