欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

一、IP白名單控制概述

1.1 什么是IP白名單

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

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

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

1.2 IP白名單 vs 黑名單

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

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

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

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

2.1 實(shí)現(xiàn)方案對(duì)比

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

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

實(shí)現(xiàn)方式

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

優(yōu)點(diǎn)

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

缺點(diǎn)

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

適用場(chǎng)景

  • 簡(jiǎn)單項(xiàng)目或?qū)Π踩蟛桓叩膱?chǎng)景。
  • 需要完全自定義邏輯(如動(dòng)態(tài)加載白名單)。

2. Spring Security 集成

實(shí)現(xiàn)方式

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

優(yōu)點(diǎn)

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

缺點(diǎn)

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

適用場(chǎng)景

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

3. AOP(面向切面編程)

實(shí)現(xiàn)方式

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

優(yōu)點(diǎn)

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

缺點(diǎn)

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

適用場(chǎng)景

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

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

實(shí)現(xiàn)方式

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

優(yōu)點(diǎn)

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

缺點(diǎn)

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

適用場(chǎng)景

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

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

實(shí)現(xiàn)方式

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

優(yōu)點(diǎn)

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

缺點(diǎn)

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

適用場(chǎng)景

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

6. 基于Interceptor的IP白名單

優(yōu)點(diǎn)

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

缺點(diǎn)

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

適用場(chǎng)景

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

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

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

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

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

1.1 添加依賴

Spring Boot 默認(rèn)支持 Servlet API,無(wú)需額外依賴。

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
 * 作用:攔截請(qǐng)求,檢查客戶端 IP 是否在白名單中
 */
@Component
public class IpWhiteListFilter implements Filter {

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

    // 用于存儲(chǔ)白名單的 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());
    }

    /**
     * 處理請(qǐng)求
     */
    @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); // 獲取真實(shí) IP
        if (whiteList.contains(clientIP)) {
            chain.doFilter(request, response); // IP 在白名單中,放行
        } else {
            httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "IP 未授權(quán)訪問(wèn)");
        }
    }

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

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

1.4 注冊(cè) Filter(可選)

如果未使用 @Component 注解,可通過(guò)配置類注冊(cè):

@Configuration
public class FilterConfig {

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

3.2 Spring Security 實(shí)現(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')") // 支持多個(gè) IP
                .and()
            .csrf().disable(); // 關(guān)閉 CSRF 保護(hù)
    }
}

3.3 AOP 實(shí)現(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;

/**
 * 自定義注解,標(biāo)記需要 IP 白名單保護(hù)的方法
 */
@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)訪問(wèn)");
        }
    }

    /**
     * 獲取客戶端真實(shí) 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 動(dòng)態(tài)白名單(數(shù)據(jù)庫(kù) + 緩存)

4.1 添加依賴

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

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

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

4.3 創(chuàng)建實(shí)體類

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ù)庫(kù)
        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)訪問(wèn)");
}

3.5 Linux 防火墻實(shí)現(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. 項(xiàng)目初始化與依賴配置

首先創(chuàng)建一個(gè)標(biāo)準(zhǔn)的Spring Boot項(xiàng)目,添加必要依賴:

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- Lombok簡(jiǎn)化代碼 -->
    <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è)計(jì)

創(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-實(shí)際攔截
     */
    private boolean monitorMode = false;
    
    /**
     * 允許的IP段,支持CIDR表示法
     */
    private List<String> allowedIpRanges = new ArrayList<>();
}

對(duì)應(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工具類實(shí)現(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";
    
    /**
     * 獲取客戶端真實(shí)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();
        }
        // 處理多級(jí)代理情況
        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) {
        // 實(shí)現(xiàn)細(xì)節(jié)...
    }
    
    /**
     * 驗(yàn)證IP地址格式
     */
    public static boolean isValidIp(String ip) {
        // 實(shí)現(xiàn)細(xì)節(jié)...
    }
}

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

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

@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 {};
    
    /**
     * 拒絕時(shí)的錯(cuò)誤消息
     */
    String message() default "Access denied by IP whitelist";
}

5. 攔截器核心實(shí)現(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);
        
        // 如果都沒(méi)有注解,則跳過(guò)檢查
        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. 攔截器注冊(cè)配置

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

@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)先級(jí)
        }
    }
}

7. 控制器示例

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

@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 注意事項(xiàng)

  1. IP 獲取問(wèn)題

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

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

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

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

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

4.1 Spring Security集成概述

對(duì)于企業(yè)級(jí)應(yīng)用,使用Spring Security可以提供更專業(yè)的安全控制。我們將基于前面的基礎(chǔ)實(shí)現(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 {
        // 獲取請(qǐng)求路徑對(duì)應(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 基于表達(dá)式的安全控制

Spring Security支持使用@PreAuthorize注解實(shí)現(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) {
        // 實(shí)現(xiàn)IP檢查邏輯
        return true;
    }
}

五、生產(chǎn)級(jí)增強(qiáng)功能

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

實(shí)現(xiàn)動(dòng)態(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()));
    }
    
    // 類似方法實(shí)現(xiàn)IP段管理...
}

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

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

@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)化與緩存

實(shí)現(xiàn)本地緩存減少遠(yuǎ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));
    }
}

六、測(cè)試策略與驗(yàn)證

6.1 單元測(cè)試

針對(duì)核心工具類編寫單元測(cè)試:

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測(cè)試各種頭部情況
    }
}

6.2 集成測(cè)試

使用MockMvc測(cè)試完整流程:

@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 性能測(cè)試

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

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

7.1 安全建議

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

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

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

7.3 故障排查指南

常見問(wèn)題及解決方案:

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

八、擴(kuò)展與演進(jìn)

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

在Spring Cloud體系中,可以在網(wǎng)關(guān)層統(tǒng)一實(shí)現(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動(dòng)態(tài)變化的問(wèn)題:

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 未來(lái)演進(jìn)方向

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

九、總結(jié)與展望

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

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

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

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

相關(guān)文章

  • Java實(shí)現(xiàn)無(wú)頭雙向鏈表操作

    Java實(shí)現(xiàn)無(wú)頭雙向鏈表操作

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)無(wú)頭雙向鏈表的基本操作,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Java異常類型介紹及處理方法

    Java異常類型介紹及處理方法

    這篇文章介紹了Java異常類型介紹及處理方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • Java面試突擊為什么要用HTTPS及它的優(yōu)點(diǎn)

    Java面試突擊為什么要用HTTPS及它的優(yōu)點(diǎn)

    這篇文章主要介紹了Java面試突擊為什么要用HTTPS及它的優(yōu)點(diǎn),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-07-07
  • SpringBoot3整合Nacos?V2.3.2的詳細(xì)過(guò)程

    SpringBoot3整合Nacos?V2.3.2的詳細(xì)過(guò)程

    本文介紹了如何在?Spring?Boot?3.2.x?項(xiàng)目中整合?Nacos?2.3.2,包括依賴配置、Nacos?服務(wù)發(fā)現(xiàn)與動(dòng)態(tài)配置的配置方法,通過(guò)整合?Nacos,Spring?Boot?應(yīng)用可以實(shí)現(xiàn)高效的服務(wù)發(fā)現(xiàn)、動(dòng)態(tài)配置管理以及分布式系統(tǒng)中的靈活擴(kuò)展,感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • Java實(shí)現(xiàn)分頁(yè)查詢功能

    Java實(shí)現(xiàn)分頁(yè)查詢功能

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)分頁(yè)查詢功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • java如何獲取兩個(gè)日期的時(shí)間差

    java如何獲取兩個(gè)日期的時(shí)間差

    這篇文章主要為大家詳細(xì)介紹了java獲取兩個(gè)日期時(shí)間差的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • springboot中獲取配置文件中屬性值的幾種方式小結(jié)

    springboot中獲取配置文件中屬性值的幾種方式小結(jié)

    本文主要介紹了springboot中獲取配置文件中屬性值的幾種方式小結(jié),主要介紹了六種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-05-05
  • Maven配置項(xiàng)目依賴使用本地倉(cāng)庫(kù)的方法匯總(小結(jié))

    Maven配置項(xiàng)目依賴使用本地倉(cāng)庫(kù)的方法匯總(小結(jié))

    這篇文章主要介紹了Maven配置項(xiàng)目依賴使用本地倉(cāng)庫(kù)的方法匯總(小結(jié)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Java實(shí)現(xiàn)線程按序交替執(zhí)行的方法詳解

    Java實(shí)現(xiàn)線程按序交替執(zhí)行的方法詳解

    這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)線程按序交替執(zhí)行,文中的示例代碼講解詳細(xì),對(duì)我們了解線程有一定幫助,需要的可以參考一下
    2022-10-10
  • 詳解Springboot應(yīng)用中設(shè)置Cookie的SameSite屬性

    詳解Springboot應(yīng)用中設(shè)置Cookie的SameSite屬性

    Chrome 51 開始,瀏覽器的 Cookie 新增加了一個(gè)SameSite屬性,用來(lái)防止 CSRF 攻擊和用戶追蹤。今天通過(guò)本文給大家介紹Springboot應(yīng)用中設(shè)置Cookie的SameSite屬性,感興趣的朋友一起看看吧
    2022-01-01

最新評(píng)論