最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot中IP白名單控制實現(xiàn)限制接口訪問

 更新時間:2025年07月30日 10:17:37   作者:Clf丶憶笙  
IP白名單是一種網(wǎng)絡(luò)安全機制,通過預(yù)設(shè)允許訪問的IP地址列表實現(xiàn)對請求來源的精確控制,在Spring Boot中實現(xiàn)IP白名單有多種技術(shù)方案,下面就拉介紹一下,感興趣的可以了解一下

一、IP白名單控制概述

1.1 什么是IP白名單

IP白名單(IP Whitelist)是一種網(wǎng)絡(luò)安全機制,它通過預(yù)先定義一組被允許訪問系統(tǒng)資源的IP地址列表,實現(xiàn)對網(wǎng)絡(luò)請求來源的精確控制。只有來自白名單中IP地址的請求才會被系統(tǒng)接受和處理,其他所有來源的請求都將被拒絕。

在Spring Boot應(yīng)用中實現(xiàn)IP白名單控制具有以下核心價值:

  • 增強安全性:有效防止未授權(quán)訪問,降低惡意攻擊風(fēng)險
  • 訪問控制:精確管理可訪問系統(tǒng)的客戶端范圍
  • 資源保護:避免非預(yù)期流量消耗服務(wù)器資源
  • 合規(guī)要求:滿足某些行業(yè)對訪問控制的監(jiān)管要求

1.2 IP白名單 vs 黑名單

特性IP白名單IP黑名單
控制邏輯默認拒絕,明確允許默認允許,明確拒絕
安全性更高,僅已知安全IP可訪問較低,新型攻擊源可能不在名單中
維護成本較高,需要持續(xù)更新合法IP較低,只需添加已知惡意IP
適用場景內(nèi)部系統(tǒng)、高安全要求接口公開服務(wù)、需要阻止特定惡意源
誤殺可能性可能誤拒絕合法但未登記的IP可能漏過未登記的惡意IP

1.3 IP白名單的應(yīng)用場景

  1. 內(nèi)部管理系統(tǒng):限制只有公司內(nèi)網(wǎng)或VPN IP可以訪問
  2. 支付接口:確保只有支付網(wǎng)關(guān)的服務(wù)器IP可以調(diào)用
  3. 數(shù)據(jù)同步接口:僅允許合作伙伴的指定服務(wù)器IP訪問
  4. 管理后臺:防止未授權(quán)的管理員訪問
  5. 第三方服務(wù)集成:限定合作方的調(diào)用來源

二、Spring Boot中實現(xiàn)IP白名單的技術(shù)選型

2.1 實現(xiàn)方案對比

在 Spring Boot 中實現(xiàn) IP 白名單功能時,可以選擇多種技術(shù)方案。以下是常見的 技術(shù)選型 及其適用場景、優(yōu)缺點分析:

1. 自定義 Filter 實現(xiàn)

實現(xiàn)方式

  • 通過實現(xiàn) javax.servlet.Filter 接口,在 doFilter 方法中檢查請求的 IP 是否在白名單中。
  • 配合 @Component 注解注冊為 Spring Bean,并配置攔截路徑。

優(yōu)點

  • 簡單直接:無需依賴額外框架,代碼實現(xiàn)靈活。
  • 低耦合:與 Spring Security 無關(guān),適合輕量級需求。
  • 可擴展性強:支持動態(tài)更新白名單(如從數(shù)據(jù)庫加載)。

缺點

  • 需要手動處理 IP 獲取邏輯:需注意代理服務(wù)器(如 Nginx)后的真實 IP 獲取。
  • 缺乏安全框架集成:無法與 Spring Security 的權(quán)限控制無縫結(jié)合。

適用場景

  • 簡單項目或?qū)Π踩蟛桓叩膱鼍啊?/li>
  • 需要完全自定義邏輯(如動態(tài)加載白名單)。

2. Spring Security 集成

實現(xiàn)方式

  • 使用 Spring Security 提供的 hasIpAddress 方法,配置白名單。
  • 對于多 IP 白名單,需結(jié)合自定義表達式或策略。

優(yōu)點

  • 與安全框架無縫集成:可與其他安全規(guī)則(如角色權(quán)限)結(jié)合。
  • 配置靈活:支持基于路徑的細粒度控制。

缺點

  • 配置復(fù)雜度較高:需要編寫自定義表達式或策略類。
  • 不支持通配符:直接配置時僅支持精確匹配。

適用場景

  • 已使用 Spring Security 的項目。
  • 需要將 IP 白名單與其他安全規(guī)則(如 JWT、OAuth)結(jié)合。

3. AOP(面向切面編程)

實現(xiàn)方式

  • 使用 @Aspect 定義切面,在方法執(zhí)行前檢查 IP 是否在白名單中。
  • 適用于對特定方法或類的訪問控制。

優(yōu)點

  • 細粒度控制:可針對具體方法或類實現(xiàn) IP 攔截。
  • 解耦業(yè)務(wù)邏輯:安全邏輯與業(yè)務(wù)代碼分離。

缺點

  • 性能開銷:AOP 會增加方法調(diào)用的額外開銷。
  • IP 獲取復(fù)雜:需在切面中獲取 HttpServletRequest 對象。

適用場景

  • 需要對特定方法(如敏感接口)進行 IP 校驗。
  • 與業(yè)務(wù)邏輯解耦需求較高的場景。

4. 動態(tài)白名單(結(jié)合數(shù)據(jù)庫)

實現(xiàn)方式

  • 將白名單存儲在數(shù)據(jù)庫中,通過定時任務(wù)或緩存刷新機制動態(tài)加載。
  • 可結(jié)合 Redis 緩存提高性能。

優(yōu)點

  • 靈活性高:無需重啟服務(wù)即可更新白名單。
  • 適合生產(chǎn)環(huán)境:支持動態(tài)管理 IP 列表。

缺點

  • 實現(xiàn)復(fù)雜度較高:需處理數(shù)據(jù)庫連接、緩存更新等邏輯。
  • 性能依賴數(shù)據(jù)庫:頻繁查詢數(shù)據(jù)庫可能影響性能。

適用場景

  • 白名單需要頻繁更新的場景。
  • 多租戶系統(tǒng)或需要動態(tài)權(quán)限管理的系統(tǒng)。

5. 使用 Linux 防火墻(iptables/nftables)

實現(xiàn)方式

  • 通過 Linux 命令行配置防火墻規(guī)則,限制訪問 IP。
  • 與 Spring Boot 無關(guān),屬于操作系統(tǒng)層面的控制。

優(yōu)點

  • 高性能:由操作系統(tǒng)直接處理,無需應(yīng)用層邏輯。
  • 簡單高效:適合服務(wù)器級別的全局控制。

缺點

  • 不可動態(tài)更新:需手動執(zhí)行命令或腳本。
  • 缺乏靈活性:無法針對具體接口或方法控制。

適用場景

  • 服務(wù)器級別的全局訪問控制。
  • 與 Spring Boot 應(yīng)用無關(guān)的基礎(chǔ)設(shè)施防護。

6. 基于Interceptor的IP白名單

優(yōu)點

  • 與 Spring MVC 集成良好:由于攔截器是 Spring MVC 的一部分,因此它能夠很好地集成到現(xiàn)有的 Spring Boot 應(yīng)用程序中。
  • 適用于控制器級別的過濾:對于那些希望基于控制器或 API 級別進行 IP 訪問控制的應(yīng)用來說,這是一個理想的選擇。
  • 靈活性高:可以根據(jù)不同的 URL 模式應(yīng)用不同的攔截規(guī)則,使得可以在不同的場景下靈活運用。

缺點

  • 不適合全局過濾:對于不在控制器中的資源(例如靜態(tài)資源),可能無法有效攔截。如果需要對整個應(yīng)用程序?qū)嵤?IP 白名單策略,則可能不是最佳選擇。
  • 性能開銷:雖然攔截器的性能開銷相對較小,但在高并發(fā)情況下,仍然需要注意其對系統(tǒng)性能的影響。

適用場景

  • 需要對特定控制器或 API 進行 IP 訪問控制的應(yīng)用:比如某些敏感的操作只能由特定的 IP 地址執(zhí)行,這時可以使用攔截器來限制訪問。
  • 已構(gòu)建了復(fù)雜的 Spring MVC 應(yīng)用程序的項目:如果您的應(yīng)用程序已經(jīng)大量使用了 Spring MVC 的特性,那么使用攔截器將是一個自然且易于維護的選擇。
  • 輕量級的 IP 白名單需求:當您只需要簡單的 IP 白名單功能而不希望引入如 Spring Security 等較重的安全框架時,攔截器提供了一個輕便的解決方案。

6. 技術(shù)選型對比表

技術(shù)方案優(yōu)點缺點適用場景
自定義 Filter簡單直接,靈活性高需手動處理 IP 獲取邏輯輕量級項目或動態(tài)白名單需求
Spring Security與安全框架集成,配置靈活配置復(fù)雜,不支持通配符已使用 Spring Security 的項目
AOP細粒度控制,解耦業(yè)務(wù)邏輯性能開銷,IP 獲取復(fù)雜特定方法或類的訪問控制
動態(tài)白名單靈活,適合生產(chǎn)環(huán)境實現(xiàn)復(fù)雜,依賴數(shù)據(jù)庫性能多租戶系統(tǒng)或動態(tài)管理需求
基于 Interceptor與 Spring MVC 集成良好,適用于控制器層面的過濾不適合全局過濾,如靜態(tài)資源等控制器級別的 IP 訪問控制
Linux 防火墻高性能,簡單高效不可動態(tài)更新,缺乏靈活性服務(wù)器級別全局控制

三、完整實現(xiàn)方案

3.1 自定義 Filter 實現(xiàn) IP 白名單

1.1 添加依賴

Spring Boot 默認支持 Servlet API,無需額外依賴。

1.2 創(chuàng)建配置文件

application.yml 中配置白名單:

ip:
  whitelist: "192.168.1.1, 192.168.1.2"

1.3 創(chuàng)建 Filter 類

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * 自定義 IP 白名單 Filter
 * 作用:攔截請求,檢查客戶端 IP 是否在白名單中
 */
@Component
public class IpWhiteListFilter implements Filter {

    @Value("${ip.whitelist}")
    private String whitelistStr;

    // 用于存儲白名單的 List
    private List<String> whiteList;

    /**
     * 初始化白名單
     */
    @Override
    public void init(FilterConfig filterConfig) {
        whiteList = Arrays.stream(whitelistStr.split(","))
                .map(String::trim)
                .collect(java.util.stream.Collectors.toList());
    }

    /**
     * 處理請求
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        String clientIP = getClientIP(httpRequest); // 獲取真實 IP
        if (whiteList.contains(clientIP)) {
            chain.doFilter(request, response); // IP 在白名單中,放行
        } else {
            httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "IP 未授權(quán)訪問");
        }
    }

    /**
     * 獲取客戶端真實 IP(支持代理服務(wù)器)
     */
    private String getClientIP(HttpServletRequest request) {
        // 從 X-Forwarded-For 頭獲取真實 IP
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr(); // 如果沒有代理,直接獲取遠程地址
        }
        return ip;
    }

    @Override
    public void destroy() {
        // 清理資源
    }
}

1.4 注冊 Filter(可選)

如果未使用 @Component 注解,可通過配置類注冊:

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<IpWhiteListFilter> ipWhiteListFilter(IpWhiteListFilter filter) {
        FilterRegistrationBean<IpWhiteListFilter> registration = new FilterRegistrationBean<>(filter);
        registration.addUrlPatterns("/*"); // 攔截所有請求
        return registration;
    }
}

3.2 Spring Security 實現(xiàn) IP 白名單

2.1 添加依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2.2 配置白名單

application.yml 中配置白名單:

ip:
  whitelist: "192.168.1.1, 192.168.1.2"

2.3 創(chuàng)建 Security 配置類

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import java.util.Arrays;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${ip.whitelist}")
    private String[] whiteList;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/**")
                .access("hasIpAddress('192.168.1.1') or hasIpAddress('192.168.1.2')") // 支持多個 IP
                .and()
            .csrf().disable(); // 關(guān)閉 CSRF 保護
    }
}

3.3 AOP 實現(xiàn) IP 白名單

3.1 添加依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

3.2 創(chuàng)建自定義注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定義注解,標記需要 IP 白名單保護的方法
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IpWhiteList {
}

3.3 創(chuàng)建 AOP 切面類

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Value;
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.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * AOP 切面類:檢查 IP 是否在白名單中
 */
@Aspect
@Component
public class IpWhiteListAspect {

    @Value("${ip.whitelist}")
    private String whitelistStr;

    private List<String> whiteList;

    public IpWhiteListAspect() {
        // 初始化白名單
        whiteList = Arrays.stream(whitelistStr.split(","))
                .map(String::trim)
                .collect(java.util.stream.Collectors.toList());
    }

    /**
     * 切面邏輯:在方法執(zhí)行前檢查 IP
     */
    @Around("@annotation(IpWhiteList)")
    public Object checkIp(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        String clientIP = getClientIP(request);

        if (whiteList.contains(clientIP)) {
            return joinPoint.proceed(); // IP 在白名單中,繼續(xù)執(zhí)行方法
        } else {
            throw new AccessDeniedException("IP 未授權(quán)訪問");
        }
    }

    /**
     * 獲取客戶端真實 IP(支持代理服務(wù)器)
     */
    private String getClientIP(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}

3.4 在方法上使用注解

@RestController
public class DemoController {

    @IpWhiteList
    @GetMapping("/api/test")
    public String test() {
        return "Access granted";
    }
}

3.4 動態(tài)白名單(數(shù)據(jù)庫 + 緩存)

4.1 添加依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

4.2 創(chuàng)建數(shù)據(jù)庫表

CREATE TABLE sys_ip_whitelist (
    id INT PRIMARY KEY AUTO_INCREMENT,
    ip VARCHAR(45) NOT NULL
);

4.3 創(chuàng)建實體類

import jakarta.persistence.*;

@Entity
@Table(name = "sys_ip_whitelist")
public class SysIpWhitelist {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String ip;

    // Getters and Setters
}

4.4 創(chuàng)建 Mapper 接口

import org.springframework.data.jpa.repository.JpaRepository;

public interface SysIpWhitelistRepository extends JpaRepository<SysIpWhitelist, Long> {
    SysIpWhitelist findByIp(String ip);
}

4.5 創(chuàng)建 Service 類

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class WhiteListService {

    @Autowired
    private SysIpWhitelistRepository repository;

    // 使用 Redis 緩存白名單(示例代碼)
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private static final String WHITE_LIST_KEY = "ip:white_list";

    /**
     * 檢查 IP 是否在白名單中(支持緩存)
     */
    public boolean isWhiteListed(String ip) {
        // 先查緩存
        List<String> cachedList = (List<String>) redisTemplate.opsForValue().get(WHITE_LIST_KEY);
        if (cachedList != null && cachedList.contains(ip)) {
            return true;
        }

        // 再查數(shù)據(jù)庫
        SysIpWhitelist entity = repository.findByIp(ip);
        if (entity != null) {
            // 更新緩存
            List<String> list = repository.findAll().stream().map(SysIpWhitelist::getIp).collect(Collectors.toList());
            redisTemplate.opsForValue().set(WHITE_LIST_KEY, list, 1, TimeUnit.MINUTES);
            return true;
        }
        return false;
    }
}

4.6 在 Filter 或 AOP 中調(diào)用 Service

@Autowired
private WhiteListService whiteListService;

// 在 doFilter 或 checkIp 方法中調(diào)用
if (!whiteListService.isWhiteListed(clientIP)) {
    response.sendError(HttpServletResponse.SC_FORBIDDEN, "IP 未授權(quán)訪問");
}

3.5 Linux 防火墻實現(xiàn) IP 白名單

5.1 安裝 iptables

sudo apt update
sudo apt install iptables

5.2 配置白名單規(guī)則

# 允許白名單 IP
sudo iptables -A INPUT -s 192.168.1.1 -j ACCEPT
sudo iptables -A INPUT -s 192.168.1.2 -j ACCEPT

# 拒絕其他所有 IP
sudo iptables -A INPUT -j DROP

5.3 保存規(guī)則(可選)

# 安裝保存工具
sudo apt install iptables-persistent

# 保存規(guī)則
sudo netfilter-persistent save

3.6 基于Interceptor的IP白名單

1. 項目初始化與依賴配置

首先創(chuàng)建一個標準的Spring Boot項目,添加必要依賴:

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- Lombok簡化代碼 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    
    <!-- 配置處理 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

2. IP白名單配置設(shè)計

創(chuàng)建配置類IpWhitelistProperties

@ConfigurationProperties(prefix = "security.ip.whitelist")
@Data
public class IpWhitelistProperties {
    /**
     * 是否啟用IP白名單功能
     */
    private boolean enabled = false;
    
    /**
     * 全局IP白名單列表
     */
    private List<String> globalAllowedIps = new ArrayList<>();
    
    /**
     * 監(jiān)控模式:true-只記錄不攔截,false-實際攔截
     */
    private boolean monitorMode = false;
    
    /**
     * 允許的IP段,支持CIDR表示法
     */
    private List<String> allowedIpRanges = new ArrayList<>();
}

對應(yīng)的application.yml配置示例:

security:
  ip:
    whitelist:
      enabled: true
      global-allowed-ips:
        - 192.168.1.100
        - 172.16.0.50
      allowed-ip-ranges:
        - 10.0.0.0/8
        - 192.168.0.0/16
      monitor-mode: false

3. IP工具類實現(xiàn)

創(chuàng)建IpUtils工具類處理IP相關(guān)邏輯:

public class IpUtils {
    private static final String UNKNOWN = "unknown";
    private static final String LOCALHOST_IPV4 = "127.0.0.1";
    private static final String LOCALHOST_IPV6 = "0:0:0:0:0:0:0:1";
    
    /**
     * 獲取客戶端真實IP地址
     */
    public static String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 處理多級代理情況
        if (ip != null && ip.contains(",")) {
            ip = ip.substring(0, ip.indexOf(",")).trim();
        }
        return LOCALHOST_IPV6.equals(ip) ? LOCALHOST_IPV4 : ip;
    }
    
    /**
     * 檢查IP是否匹配CIDR表示法的IP段
     */
    public static boolean isIpInRange(String ip, String cidr) {
        // 實現(xiàn)細節(jié)...
    }
    
    /**
     * 驗證IP地址格式
     */
    public static boolean isValidIp(String ip) {
        // 實現(xiàn)細節(jié)...
    }
}

4. 自定義注解設(shè)計

創(chuàng)建@IpWhitelist注解支持方法級別的控制:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IpWhitelist {
    /**
     * 是否啟用IP白名單檢查
     */
    boolean enabled() default true;
    
    /**
     * 特定于該接口的允許IP列表
     */
    String[] allowedIps() default {};
    
    /**
     * 特定于該接口的允許IP段(CIDR)
     */
    String[] allowedIpRanges() default {};
    
    /**
     * 拒絕時的錯誤消息
     */
    String message() default "Access denied by IP whitelist";
}

5. 攔截器核心實現(xiàn)

創(chuàng)建IpWhitelistInterceptor攔截器:

@RequiredArgsConstructor
public class IpWhitelistInterceptor implements HandlerInterceptor {
    private final IpWhitelistProperties properties;
    private final ObjectMapper objectMapper;
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!properties.isEnabled()) {
            return true;
        }
        
        // 處理HandlerMethod情況
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        
        // 檢查類和方法上的注解
        IpWhitelist classAnnotation = handlerMethod.getBeanType().getAnnotation(IpWhitelist.class);
        IpWhitelist methodAnnotation = method.getAnnotation(IpWhitelist.class);
        
        // 如果都沒有注解,則跳過檢查
        if (classAnnotation == null && methodAnnotation == null) {
            return true;
        }
        
        // 合并注解配置
        boolean enabled = methodAnnotation != null ? methodAnnotation.enabled() : 
                         classAnnotation.enabled();
        String[] allowedIps = methodAnnotation != null && methodAnnotation.allowedIps().length > 0 ? 
                             methodAnnotation.allowedIps() : 
                             classAnnotation != null ? classAnnotation.allowedIps() : new String[0];
        String[] allowedIpRanges = methodAnnotation != null && methodAnnotation.allowedIpRanges().length > 0 ? 
                                  methodAnnotation.allowedIpRanges() : 
                                  classAnnotation != null ? classAnnotation.allowedIpRanges() : new String[0];
        String message = methodAnnotation != null ? methodAnnotation.message() : 
                        classAnnotation != null ? classAnnotation.message() : "Access denied by IP whitelist";
        
        if (!enabled) {
            return true;
        }
        
        String clientIp = IpUtils.getClientIp(request);
        
        // 檢查全局白名單
        boolean isAllowed = properties.getGlobalAllowedIps().contains(clientIp) || 
                           properties.getAllowedIpRanges().stream()
                               .anyMatch(range -> IpUtils.isIpInRange(clientIp, range));
        
        // 檢查注解指定的白名單
        if (!isAllowed) {
            isAllowed = Arrays.stream(allowedIps).anyMatch(ip -> ip.equals(clientIp)) || 
                       Arrays.stream(allowedIpRanges)
                           .anyMatch(range -> IpUtils.isIpInRange(clientIp, range));
        }
        
        if (!isAllowed) {
            if (properties.isMonitorMode()) {
                log.warn("IP whitelist monitor mode triggered. Denied IP: {}", clientIp);
                return true;
            }
            
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.setStatus(HttpStatus.FORBIDDEN.value());
            response.getWriter().write(objectMapper.writeValueAsString(
                Map.of(
                    "code", 403,
                    "message", message,
                    "data", null
                )
            ));
            return false;
        }
        
        return true;
    }
}

6. 攔截器注冊配置

創(chuàng)建Web配置類注冊攔截器:

@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
    private final IpWhitelistProperties ipWhitelistProperties;
    private final ObjectMapper objectMapper;
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        if (ipWhitelistProperties.isEnabled()) {
            registry.addInterceptor(new IpWhitelistInterceptor(ipWhitelistProperties, objectMapper))
                .addPathPatterns("/**")
                .order(Ordered.HIGHEST_PRECEDENCE); // 設(shè)置最高優(yōu)先級
        }
    }
}

7. 控制器示例

創(chuàng)建測試控制器驗證功能:

@RestController
@RequestMapping("/api")
public class TestController {
    
    @GetMapping("/public")
    public String publicApi() {
        return "This is a public API";
    }
    
    @IpWhitelist
    @GetMapping("/secure")
    public String secureApi() {
        return "This is a secure API with IP whitelist";
    }
    
    @IpWhitelist(
        allowedIps = {"192.168.1.100", "172.16.0.50"},
        allowedIpRanges = {"10.0.0.0/8"},
        message = "Custom IP restriction"
    )
    @GetMapping("/custom")
    public String customApi() {
        return "This API has custom IP whitelist rules";
    }
}

3.7 注意事項

  1. IP 獲取問題

    • 如果使用 Nginx 等反向代理,需從 X-Forwarded-For 頭獲取真實 IP。
    • 示例代碼已處理代理邏輯。
  2. 通配符支持

    • 如果需要支持 CIDR 格式(如 192.168.1.0/24),需自行實現(xiàn) CIDR 匹配邏輯。
  3. 性能優(yōu)化

    • 動態(tài)白名單建議使用緩存(如 Redis)減少數(shù)據(jù)庫查詢。
    • 高并發(fā)場景下,F(xiàn)ilter 或 AOP 的性能開銷需評估。
  4. 安全性

    • 確保白名單邏輯不被繞過(如偽造 X-Forwarded-For 頭)。
    • 結(jié)合其他安全措施(如 HTTPS、JWT)增強防護。

四、進階實現(xiàn):基于Spring Security的專業(yè)方案

4.1 Spring Security集成概述

對于企業(yè)級應(yīng)用,使用Spring Security可以提供更專業(yè)的安全控制。我們將基于前面的基礎(chǔ)實現(xiàn),重構(gòu)為Spring Security方案。

添加Spring Security依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

4.2 自定義AuthenticationFilter

創(chuàng)建IpAuthenticationFilter

public class IpAuthenticationFilter extends OncePerRequestFilter {
    private final IpWhitelistProperties properties;
    private final ObjectMapper objectMapper;
    
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 
            throws ServletException, IOException {
        // 獲取請求路徑對應(yīng)的HandlerMethod
        HandlerExecutionChain handlerExecutionChain = null;
        try {
            handlerExecutionChain = ((DispatcherServlet) request.getAttribute(DispatcherServlet.class.getName() + ".CONTEXT"))
                .getHandler(request);
        } catch (Exception e) {
            filterChain.doFilter(request, response);
            return;
        }
        
        if (handlerExecutionChain == null || !(handlerExecutionChain.getHandler() instanceof HandlerMethod)) {
            filterChain.doFilter(request, response);
            return;
        }
        
        HandlerMethod handlerMethod = (HandlerMethod) handlerExecutionChain.getHandler();
        // 后續(xù)邏輯與Interceptor類似...
    }
}

4.3 安全配置類

創(chuàng)建安全配置類:

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private final IpWhitelistProperties ipWhitelistProperties;
    private final ObjectMapper objectMapper;
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .addFilterBefore(new IpAuthenticationFilter(ipWhitelistProperties, objectMapper), 
                           UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests()
                .antMatchers("/api/public").permitAll()
                .anyRequest().authenticated()
            .and()
            .formLogin().disable()
            .httpBasic().disable();
    }
}

4.4 基于表達式的安全控制

Spring Security支持使用@PreAuthorize注解實現(xiàn)更靈活的控制:

@RestController
@RequestMapping("/api/v2")
public class SecureController {
    
    @PreAuthorize("@ipSecurityService.isAllowed(#request)")
    @GetMapping("/expression")
    public String expressionBasedApi(HttpServletRequest request) {
        return "This API uses expression-based IP control";
    }
}

@Service
public class IpSecurityService {
    public boolean isAllowed(HttpServletRequest request) {
        // 實現(xiàn)IP檢查邏輯
        return true;
    }
}

五、生產(chǎn)級增強功能

5.1 動態(tài)IP白名單管理

實現(xiàn)動態(tài)更新白名單而不重啟應(yīng)用:

@Service
public class DynamicIpWhitelistService {
    private final List<String> dynamicAllowedIps = new CopyOnWriteArrayList<>();
    private final List<String> dynamicAllowedIpRanges = new CopyOnWriteArrayList<>();
    
    public synchronized void addAllowedIp(String ip) {
        if (IpUtils.isValidIp(ip) && !dynamicAllowedIps.contains(ip)) {
            dynamicAllowedIps.add(ip);
        }
    }
    
    public synchronized void removeAllowedIp(String ip) {
        dynamicAllowedIps.remove(ip);
    }
    
    public synchronized void reloadIps(List<String> ips) {
        dynamicAllowedIps.clear();
        dynamicAllowedIps.addAll(ips.stream()
            .filter(IpUtils::isValidIp)
            .collect(Collectors.toList()));
    }
    
    // 類似方法實現(xiàn)IP段管理...
}

5.2 結(jié)合Redis的分布式IP白名單

對于分布式系統(tǒng),白名單需要集中存儲:

@Configuration
public class RedisIpWhitelistConfig {
    
    @Bean
    public RedisTemplate<String, String> ipWhitelistRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, String> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new StringRedisSerializer());
        return template;
    }
}

@Service
@RequiredArgsConstructor
public class RedisIpWhitelistService {
    private static final String WHITELIST_KEY = "ip:whitelist";
    private static final String WHITELIST_RANGES_KEY = "ip:whitelist:ranges";
    
    private final RedisTemplate<String, String> redisTemplate;
    
    public boolean isAllowed(String ip) {
        // 檢查精確IP
        Boolean isMember = redisTemplate.opsForSet().isMember(WHITELIST_KEY, ip);
        if (Boolean.TRUE.equals(isMember)) {
            return true;
        }
        
        // 檢查IP段
        Set<String> ranges = redisTemplate.opsForSet().members(WHITELIST_RANGES_KEY);
        if (ranges != null) {
            return ranges.stream().anyMatch(range -> IpUtils.isIpInRange(ip, range));
        }
        
        return false;
    }
    
    // 其他管理方法...
}

5.3 性能優(yōu)化與緩存

實現(xiàn)本地緩存減少遠程調(diào)用:

@Service
public class CachedIpWhitelistService {
    private final LoadingCache<String, Boolean> ipCheckCache;
    
    public CachedIpWhitelistService(RedisIpWhitelistService redisService) {
        this.ipCheckCache = Caffeine.newBuilder()
            .maximumSize(10_000)
            .expireAfterWrite(5, TimeUnit.MINUTES)
            .build(redisService::isAllowed);
    }
    
    public boolean isAllowed(String ip) {
        return Boolean.TRUE.equals(ipCheckCache.get(ip));
    }
}

六、測試策略與驗證

6.1 單元測試

針對核心工具類編寫單元測試:

class IpUtilsTest {
    
    @Test
    void testIsIpInRange() {
        assertTrue(IpUtils.isIpInRange("192.168.1.100", "192.168.1.0/24"));
        assertFalse(IpUtils.isIpInRange("10.0.0.5", "192.168.1.0/24"));
    }
    
    @Test
    void testGetClientIp() {
        // 模擬HttpServletRequest測試各種頭部情況
    }
}

6.2 集成測試

使用MockMvc測試完整流程:

@SpringBootTest
@AutoConfigureMockMvc
class IpWhitelistIntegrationTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @Test
    @WithMockUser
    void testPublicApi() throws Exception {
        mockMvc.perform(get("/api/public"))
            .andExpect(status().isOk());
    }
    
    @Test
    @WithMockUser
    void testSecureApiWithAllowedIp() throws Exception {
        mockMvc.perform(get("/api/secure").with(request -> {
                request.setRemoteAddr("192.168.1.100");
                return request;
            }))
            .andExpect(status().isOk());
    }
    
    @Test
    @WithMockUser
    void testSecureApiWithDeniedIp() throws Exception {
        mockMvc.perform(get("/api/secure").with(request -> {
                request.setRemoteAddr("10.1.2.3");
                return request;
            }))
            .andExpect(status().isForbidden());
    }
}

6.3 性能測試

使用JMeter模擬不同負載下的表現(xiàn):

七、生產(chǎn)環(huán)境最佳實踐

7.1 安全建議

  1. 最小權(quán)限原則:只添加必要的IP到白名單
  2. 定期審計:每月審查白名單,移除不再需要的IP
  3. 日志記錄:詳細記錄所有被拒絕的訪問嘗試
  4. 監(jiān)控告警:對異常訪問模式設(shè)置告警
  5. 備份機制:定期備份白名單配置

7.2 性能調(diào)優(yōu)

  1. 緩存策略:對IP檢查結(jié)果進行適當緩存
  2. 異步檢查:對于非關(guān)鍵路徑可以考慮異步驗證
  3. CIDR優(yōu)化:將IP段檢查算法優(yōu)化為O(1)復(fù)雜度
  4. 并發(fā)控制:使用線程安全的數(shù)據(jù)結(jié)構(gòu)
  5. 預(yù)熱機制:應(yīng)用啟動時預(yù)加載常用IP

7.3 故障排查指南

常見問題及解決方案:

問題現(xiàn)象可能原因解決方案
合法IP被拒絕IP獲取不正確檢查X-Forwarded-For等頭部配置
白名單修改后不生效緩存未刷新實現(xiàn)配置變更通知機制
性能下降IP檢查成為瓶頸引入緩存、優(yōu)化算法或水平擴展
分布式環(huán)境不一致各節(jié)點白名單不同步使用集中式存儲如Redis
IPv6支持問題只配置了IPv4確保同時支持IPv4和IPv6格式

八、擴展與演進

8.1 結(jié)合微服務(wù)架構(gòu)

在Spring Cloud體系中,可以在網(wǎng)關(guān)層統(tǒng)一實現(xiàn)IP白名單:

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("secure-service", r -> r.path("/api/secure/**")
            .filters(f -> f.filter(new IpWhitelistGatewayFilter()))
            .uri("lb://secure-service"))
        .build();
}

8.2 Kubernetes環(huán)境適配

在K8s中需要考慮Pod IP動態(tài)變化的問題:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-whitelist
spec:
  podSelector:
    matchLabels:
      app: spring-boot-app
  ingress:
  - from:
    - ipBlock:
        cidr: 192.168.1.0/24
    ports:
    - protocol: TCP
      port: 8080

8.3 未來演進方向

  1. 機器學(xué)習(xí)分析:自動識別異常IP并動態(tài)調(diào)整白名單
  2. 區(qū)塊鏈存證:將白名單變更記錄上鏈確保不可篡改
  3. 零信任整合:與零信任架構(gòu)深度集成
  4. IoT擴展:支持設(shè)備指紋等更多維度的認證
  5. 量子安全:為后量子時代提前準備加密方案

九、總結(jié)與展望

本文詳細探討了在Spring Boot應(yīng)用中實現(xiàn)IP白名單控制的多種方案,從基礎(chǔ)的Interceptor實現(xiàn)到基于Spring Security的專業(yè)方案,再到生產(chǎn)級的增強功能和分布式環(huán)境適配。通過本教程,您應(yīng)該能夠:

  1. 深入理解IP白名單的原理和價值
  2. 掌握在Spring Boot中實現(xiàn)IP控制的多種技術(shù)
  3. 具備構(gòu)建生產(chǎn)級IP白名單系統(tǒng)的能力
  4. 了解相關(guān)的最佳實踐和優(yōu)化策略

IP白名單作為網(wǎng)絡(luò)安全的基礎(chǔ)設(shè)施之一,在云原生和微服務(wù)架構(gòu)不斷演進的今天,仍然發(fā)揮著不可替代的作用。未來,隨著邊緣計算和5G技術(shù)的普及,IP白名單技術(shù)可能會與更多新興技術(shù)融合,形成更智能、更靈活的訪問控制體系。

到此這篇關(guān)于SpringBoot中IP白名單控制實現(xiàn)限制接口訪問的文章就介紹到這了,更多相關(guān)SpringBoot IP白名單 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Java實現(xiàn)多線程的三種方式

    詳解Java實現(xiàn)多線程的三種方式

    線程(英語:thread)是操作系統(tǒng)能夠進行運算調(diào)度的最小單位。它被包含在進程之中,是進程中的實際運作單位。本文總結(jié)了Java多線程是三種實現(xiàn)方式,需要的可以參考一下
    2022-03-03
  • mybatis-plus如何配置自定義數(shù)據(jù)類型TypeHandle

    mybatis-plus如何配置自定義數(shù)據(jù)類型TypeHandle

    這篇文章主要介紹了mybatis-plus如何配置自定義數(shù)據(jù)類型TypeHandle,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • JAVA技術(shù)實現(xiàn)上傳下載文件到FTP服務(wù)器(完整)

    JAVA技術(shù)實現(xiàn)上傳下載文件到FTP服務(wù)器(完整)

    這篇文章主要介紹了JAVA技術(shù)實現(xiàn)上傳下載文件到FTP服務(wù)器(完整),本文使用 Apache Jakarta Commons Net(commons-net-3.3.jar) 基于FileZilla Server服務(wù)器實現(xiàn)FTP服務(wù)器上文件的上傳/下載/刪除等操作,需要的朋友可以參考下
    2015-07-07
  • 最新評論

    织金县| 屏南县| 从化市| 定南县| 新营市| 正阳县| 青岛市| 连云港市| 洞口县| 桑植县| 杭州市| 甘德县| 孝感市| 银川市| 文昌市| 宝清县| 宁乡县| 定西市| 富锦市| 莱州市| 靖宇县| 天长市| 馆陶县| 肇州县| 台北县| 罗源县| 南城县| 邵东县| 平乐县| 喀什市| 蓬莱市| 湘西| 老河口市| 来宾市| 西贡区| 任丘市| 寻乌县| 金昌市| 江安县| 行唐县| 汝南县|