企业白名单实现【使用拦截器】
企业白名单实现功能Java【实现方式一】
-
- 是否开启白名单?
-
- 配置白名单中的ip
-
- 配置白名单中去除的路径(白名单开启后默认是全部拦截)
第一步,首先创建白名单工具类
package com.bohai.spring_boot_template.utils;import com.bohai.spring_boot_template.conf.IpWhiteListConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.util.SubnetUtils;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
import java.util.List;/*** @author hai* @version 1.0* @description: ip白名单工具类* * 功能:检查ip是否在白名单中* 获取用户的ip* 检查ip是否在CIDR范围内* @date 2025/8/29 16:21*/@Slf4jpublic class IpWhiteListUtils {@Autowiredprivate static IpWhiteListConfig ipWhiteListConfig;// 可能包含客户端真实IP的HTTP头字段列表private static final String[] IP_HEADER_CANDIDATES = {"X-Forwarded-For","Proxy-Client-IP","WL-Proxy-Client-IP","HTTP_X_FORWARDED_FOR","HTTP_X_FORWARDED","HTTP_X_CLUSTER_CLIENT_IP","HTTP_CLIENT_IP","HTTP_FORWARDED_FOR","HTTP_FORWARDED","HTTP_VIA","REMOTE_ADDR"};/*** 获取客户端真实IP地址* 考虑了代理服务器的情况,会检查多个可能的HTTP头字段** @param request HTTP请求对象* @return 客户端真实IP地址*/public static String getClientIp(HttpServletRequest request) {// 检查所有可能的HTTP头字段for (String header : IP_HEADER_CANDIDATES) {String ip = request.getHeader(header);if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {// 对于X-Forwarded-For,取第一个非unknown的IPif ("X-Forwarded-For".equalsIgnoreCase(header)) {String[] ips = ip.split(",");for (String ipPart : ips) {if (!"unknown".equalsIgnoreCase(ipPart.trim())) {return ipPart.trim();}}} else {return ip;}}}// 如果所有头字段都没有获取到IP,使用请求的远程地址return request.getRemoteAddr();}/*** 检查IP是否在CIDR范围内** @param ip 要检查的IP地址* @param cidr CIDR格式的网络地址(如192.168.1.0/24)* @return 如果IP在CIDR范围内返回true,否则返回false*/public static boolean isInCidrRange(String ip, String cidr) {try {SubnetUtils utils = new SubnetUtils(cidr);utils.setInclusiveHostCount(true); // 包含网络地址和广播地址return utils.getInfo().isInRange(ip);} catch (Exception e) {log.error("CIDR格式错误: {} - {}", cidr, e.getMessage());return false;}}/*** 检查IP是否在白名单中* 支持精确IP匹配和CIDR范围匹配** @param ip 要检查的IP地址* @param whitelist IP白名单列表(包含精确IP和CIDR格式)* @return 如果IP在白名单中返回true,否则返回false*/public static boolean isWhitelisted(String ip, List<String> whitelist) {// 遍历白名单中的所有项for (String item : whitelist) {// 如果是CIDR格式(包含斜杠)if (item.contains("/")) {if (isInCidrRange(ip, item)) {return true;}}// 如果是精确IPelse if (item.equals(ip)) {return true;}}return false;}
}
第二步、配置获取yml参数(也可以使用@Value注解)
package com.bohai.spring_boot_template.conf;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;import java.util.ArrayList;
import java.util.List;/*** @author hai* @version 1.0* @description: ip白名单配置* @date 2025/8/29 16:17*/@Component
@Data
@ConfigurationProperties(prefix = "ip.whitelist")
public class IpWhiteListConfig {private static final AntPathMatcher antPathMatcher = new AntPathMatcher();//是否开启白名单功能private boolean enable = true;//读取配置文件ip列表private List<String> ips = new ArrayList<>();//排除路径列表private List<String> excludePaths = new ArrayList<>();}
第三步、重头戏白名单过滤器
配置过滤器,达到以下条件才会放行,否则全部抛异常
package com.bohai.spring_boot_template.common.Filter;import com.bohai.spring_boot_template.common.enums.HttpStatus;
import com.bohai.spring_boot_template.conf.IpWhiteListConfig;
import com.bohai.spring_boot_template.utils.IpWhiteListUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author hai* @version 1.0* @description: ip白名单过滤器* 检查请求的客户ip是否再白名单中* @date 2025/8/29 16:33*/
@Component
@Slf4j
public class IpWhiteFilter implements Filter {/****/private static final AntPathMatcher antPathMatcher = new AntPathMatcher();@Autowiredprivate IpWhiteListConfig ipWhiteListConfig;/*** @author bohai* @description: 过过滤器初始化方法* @param:* @return:* @date: 2025/9/4 15:12*/@Overridepublic void init(FilterConfig filterConfig) {log.info("IP白名单过滤器初始化");log.info("IP白名单功能启用状态: {}", ipWhiteListConfig.isEnable());log.info("IP白名单列表: {}", ipWhiteListConfig.getIps());log.info("排除路径列表: {}", ipWhiteListConfig.getExcludePaths());}/*** @author bohai* @description: 过滤请求的主要方法* @param servletRequest Servlet请求对象* @param servletResponse Servlet响应对象* @param filterChain 过滤器链* @date: 2025/8/29 16:38*//*** 是否匹配成功,将url和设置的数据进行比对* @param path* @return*/public boolean isExcludePath(String path) {for (String pattern : ipWhiteListConfig.getExcludePaths()) {if (antPathMatcher.match(pattern, path)) {return true;}}return false;}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;String requestURI = httpRequest.getRequestURI();//1.启用了白名单,请求放行if (!ipWhiteListConfig.isEnable()){log.debug("白名单功能未启用,请求放行",requestURI);filterChain.doFilter(servletRequest,servletResponse);return;}//2. 配置了路径,请求放行if (isExcludePath(requestURI)){log.debug("路径 {} 在白名单排除列表中,放行请求", requestURI);filterChain.doFilter(servletRequest, servletResponse);return;}//3. 配置类白名单ip,请求放行String clientIp = IpWhiteListUtils.getClientIp(httpRequest);log.info("检查请求路径: {}, 客户端IP: {}", requestURI, clientIp);if (IpWhiteListUtils.isWhitelisted(clientIp,ipWhiteListConfig.getIps())){log.info("IP {} 在白名单中,放行请求 {}", clientIp, requestURI);// 一定要记得放行filterChain.doFilter(servletRequest, servletResponse);}// 情况4: 客户端IP不在白名单中,拒绝请求log.warn("IP ,或请求路径 {} 不在白名单中,拒绝访问 {}", clientIp, requestURI);httpResponse.setStatus(HttpStatus.FORBIDDEN);httpResponse.setContentType("application/json");httpResponse.getWriter().write(String.format("{\"code\": 403, \"message\": \"Access denied. IP %s not in whitelist.\"}", clientIp));}/** * @author bohai* @description: 过滤器销毁方法* @param: * @return: * @date: 2025/9/4 15:29*/ /*** 过滤器销毁方法*/@Overridepublic void destroy() {log.info("IP白名单过滤器销毁");}
}
第四步、配置yaml文件
# ip白名单
#首先判断开关,其次是路径,最后是ip地址
ip:whitelist:enable: falseexclude-paths: # 此处配置的路径所有ip都可以访问
# - /**
# - /test/**- /public/**
# - /health/**
# - /actuator/healthips:- 127.0.0.1
最后总结
排除路径就是“白名单里的绿色通道”,这些路径永远不被 IP 规则拦截。