Spring Boot 内嵌轻量级 API 防火墙实现方案

系统架构设计

  1. 防火墙配置类
@Configuration
@EnableConfigurationProperties(FirewallProperties.class)
public class FirewallConfig {
    @Bean
    public IpBlacklistManager ipBlacklistManager(FirewallProperties properties) {
        return new IpBlacklistManager(properties);
    }
    @Bean
    public RequestFilter requestFilter(IpBlacklistManager blacklistManager) {
        return new RequestFilter(blacklistManager);
    }
    @Bean
    public FirewallAdminController firewallAdminController(IpBlacklistManager blacklistManager) {
        return new FirewallAdminController(blacklistManager);
    }
}
  1. 配置文件类
@ConfigurationProperties(prefix = "api.firewall")
public class FirewallProperties {
    private boolean enabled = true;
    private int maxRequestsPerMinute = 1000;
    private List<String> defaultBlacklist = new ArrayList<>();
    private String rulesConfigPath = "classpath:firewall-rules.json";
}
  1. 黑名单管理器
@Component
public class IpBlacklistManager {
    private final Set<String> blacklist = new ConcurrentHashSet<>();
    private final FirewallProperties properties;
    
    public IpBlacklistManager(FirewallProperties properties) {
        this.properties = properties;
        this.blacklist.addAll(properties.getDefaultBlacklist());
    }
    public boolean isBlocked(String ip) {
        return blacklist.contains(ip);
    }
    public void addToBlacklist(String ip) {
        blacklist.add(ip);
    }
    public void removeFromBlacklist(String ip) {
        blacklist.remove(ip);
    }
    public List<String> getBlacklist() {
        return new ArrayList<>(blacklist);
    }
    public void clearBlacklist() {
        blacklist.clear();
    }
}
  1. 请求过滤器
@Component
public class RequestFilter implements Filter {
    private final IpBlacklistManager blacklistManager;
    private final Map<String, AtomicInteger> requestCounts = new ConcurrentHashMap<>();
    private final Map<String, Long> requestTimestamps = new ConcurrentHashMap<>();
    
    public RequestFilter(IpBlacklistManager blacklistManager) {
        this.blacklistManager = blacklistManager;
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        scheduler.scheduleAtFixedRate(this::resetRequestCounts, 1, 1, TimeUnit.MINUTES);
    }
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String ip = getClientIp(httpRequest);
        
        // 检查黑名单
        if (blacklistManager.isBlocked(ip)) {
            ((HttpServletResponse) response).sendError(HttpStatus.FORBIDDEN.value(), "IP blocked");
            return;
        }
        // 频率限制检查
        if (isRateLimited(ip)) {
            ((HttpServletResponse) response).sendError(HttpStatus.TOO_MANY_REQUESTS.value(), "Rate limit exceeded");
            return;
        }
        
        // 请求计数
        incrementRequestCount(ip);
        
        chain.doFilter(request, response);
    }
    
    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 synchronized void incrementRequestCount(String ip) {
        requestCounts.putIfAbsent(ip, new AtomicInteger(0));
        requestCounts.get(ip).incrementAndGet();
        requestTimestamps.put(ip, System.currentTimeMillis());
    }
    
    private boolean isRateLimited(String ip) {
        AtomicInteger count = requestCounts.get(ip);
        return count != null && count.get() > properties.getMaxRequestsPerMinute();
    }
    
    private void resetRequestCounts() {
        long now = System.currentTimeMillis();
        requestCounts.keySet().removeIf(ip -> {
            Long timestamp = requestTimestamps.get(ip);
            return timestamp == null || (now - timestamp) > 60000;
        });
        requestCounts.replaceAll((k, v) -> new AtomicInteger(0));
    }
}
  1. 管理控制器
@RestController
@RequestMapping("/admin/firewall")
public class FirewallAdminController {
    private final IpBlacklistManager blacklistManager;
    
    public FirewallAdminController(IpBlacklistManager blacklistManager) {
        this.blacklistManager = blacklistManager;
    }
    
    @PostMapping("/blacklist/add")
    public ResponseEntity<String> addToBlacklist(@RequestParam String ip) {
        blacklistManager.addToBlacklist(ip);
        return ResponseEntity.ok("IP added to blacklist: " + ip);
    }
    
    @PostMapping("/blacklist/remove")
    public ResponseEntity<String> removeFromBlacklist(@RequestParam String ip) {
        blacklistManager.removeFromBlacklist(ip);
        return ResponseEntity.ok("IP removed from blacklist: " + ip);
    }
    
    @GetMapping("/blacklist")
    public ResponseEntity<List<String>> getBlacklist() {
        return ResponseEntity.ok(blacklistManager.getBlacklist());
    }
    
    @PostMapping("/blacklist/clear")
    public ResponseEntity<String> clearBlacklist() {
        blacklistManager.clearBlacklist();
        return ResponseEntity.ok("Blacklist cleared");
    }
}
  1. 安全配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/admin/firewall/**").hasRole("ADMIN")
                .anyRequest().permitAll()
            .and()
            .httpBasic()
            .and()
            .csrf().disable();
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("admin")
            .password("{noop}admin123") // 生产环境应使用加密密码
            .roles("ADMIN");
    }
}

配置文件示例
application.yml:

api:
  firewall:
    enabled: true
    max-requests-per-minute: 1000
    default-blacklist:
      - "192.168.1.100"
      - "10.0.0.5"
    rules-config-path: "classpath:firewall-rules.json"

spring:
  security:
    user:
      name: admin
      password: admin123

使用说明
启用/禁用防火墙:通过配置 api.firewall.enabled 控制
管理黑名单:
添加IP到黑名单:POST /admin/firewall/blacklist/add?ip=1.2.3.4
从黑名单移除IP:POST /admin/firewall/blacklist/remove?ip=1.2.3.4
查看黑名单:GET /admin/firewall/blacklist
清空黑名单:POST /admin/firewall/blacklist/clear
配置频率限制:通过 api.firewall.max-requests-per-minute 设置

扩展建议
持久化存储:可将黑名单和配置信息保存到数据库或Redis中
分布式支持:使用Redis等分布式存储实现多实例间的黑名单同步
更复杂的规则引擎:支持基于正则表达式、请求头、参数等的复杂规则
监控和日志:添加详细的请求日志和监控指标
图形化管理界面:开发Web界面方便管理

第二种方式

  1. 动态黑名单实体类
package com.icoderoad.firewall.model;

import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class DynamicBlacklistEntry {
    private String ip;
    private LocalDateTime blockedAt;
    private LocalDateTime expireAt;
    private String reason;
    private int blockDuration; // 分钟数

    public boolean isExpired() {
        return LocalDateTime.now().isAfter(expireAt);
    }
}
  1. 防火墙规则实体类
package com.icoderoad.firewall.model;

import lombok.Data;

@Data
public class FirewallRule {
    private String pattern;
    private int maxQps;
    private int maxRequestsPerHour;
    private boolean enabled;
    private String description;
}

@Data
public class FirewallBlacklist {
    private String ip;
    private String reason;
    private LocalDateTime addedAt;
}

@Data
public class FirewallWhitelist {
    private String ip;
    private String description;
    private LocalDateTime addedAt;
}
  1. 规则管理器(增强版)
package com.icoderoad.firewall.core;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

import javax.annotation.PostConstruct;

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

import com.icoderoad.firewall.model.DynamicBlacklistEntry;
import com.icoderoad.firewall.model.FirewallBlacklist;
import com.icoderoad.firewall.model.FirewallRule;
import com.icoderoad.firewall.model.FirewallWhitelist;
import com.icoderoad.firewall.repository.RuleRepository;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class RuleManager {

    private final Map<String, FirewallRule> ruleCache = new ConcurrentHashMap<>();
    private final Map<String, FirewallBlacklist> blacklistCache = new ConcurrentHashMap<>();
    private final Map<String, FirewallWhitelist> whitelistCache = new ConcurrentHashMap<>();
    private final Map<String, DynamicBlacklistEntry> dynamicBlacklist = new ConcurrentHashMap<>();

    @Autowired
    private RuleRepository ruleRepository;

    @PostConstruct
    public void init() {
        loadRules();
        loadBlacklists();
        loadWhitelists();
        startCleanupTask();
    }

    // 定期清理过期动态黑名单
    @Scheduled(fixedRate = 60000) // 每分钟执行一次
    public void cleanupExpiredEntries() {
        int count = 0;
        for (Map.Entry<String, DynamicBlacklistEntry> entry : dynamicBlacklist.entrySet()) {
            if (entry.getValue().isExpired()) {
                dynamicBlacklist.remove(entry.getKey());
                count++;
            }
        }
        if (count > 0) {
            log.info("清理了 {} 个过期的动态黑名单条目", count);
        }
    }

    // 加载规则
    public void loadRules() {
        List<FirewallRule> rules = ruleRepository.loadRules();
        ruleCache.clear();
        rules.forEach(rule -> ruleCache.put(rule.getPattern(), rule));
        log.info("已加载 {} 条防火墙规则", rules.size());
    }

    // 加载黑名单
    public void loadBlacklists() {
        List<FirewallBlacklist> blacklists = ruleRepository.loadBlacklists();
        blacklistCache.clear();
        blacklists.forEach(bl -> blacklistCache.put(bl.getIp(), bl));
        log.info("已加载 {} 条黑名单", blacklists.size());
    }

    // 加载白名单
    public void loadWhitelists() {
        List<FirewallWhitelist> whitelists = ruleRepository.loadWhitelists();
        whitelistCache.clear();
        whitelists.forEach(wl -> whitelistCache.put(wl.getIp(), wl));
        log.info("已加载 {} 条白名单", whitelists.size());
    }

    // 添加到动态黑名单
    public void blockIp(String ip, int minutes, String reason) {
        DynamicBlacklistEntry entry = new DynamicBlacklistEntry(
                ip,
                LocalDateTime.now(),
                LocalDateTime.now().plusMinutes(minutes),
                reason,
                minutes
        );
        dynamicBlacklist.put(ip, entry);
        log.warn("IP {} 已被动态拉黑 {} 分钟,原因: {}", ip, minutes, reason);
    }

    // 检查是否在黑名单
    public boolean isBlacklisted(String ip) {
        if (blacklistCache.containsKey(ip)) return true;
        
        DynamicBlacklistEntry entry = dynamicBlacklist.get(ip);
        if (entry == null) return false;
        
        if (entry.isExpired()) {
            dynamicBlacklist.remove(ip);
            return false;
        }
        return true;
    }

    // 检查是否在白名单
    public boolean isWhitelisted(String ip) {
        return whitelistCache.containsKey(ip);
    }

    // 获取匹配的规则
    public FirewallRule getMatchingRule(String path) {
        for (Map.Entry<String, FirewallRule> entry : ruleCache.entrySet()) {
            if (Pattern.matches(entry.getKey(), path)) {
                return entry.getValue();
            }
        }
        return null;
    }

    // 管理接口调用
    public List<DynamicBlacklistEntry> getDynamicBlacklist() {
        return new ArrayList<>(dynamicBlacklist.values());
    }

    public void removeDynamicBlacklist(String ip) {
        dynamicBlacklist.remove(ip);
        log.info("已从动态黑名单中移除IP: {}", ip);
    }

    public void addToPermanentBlacklist(String ip, String reason) {
        FirewallBlacklist entry = new FirewallBlacklist();
        entry.setIp(ip);
        entry.setReason(reason);
        entry.setAddedAt(LocalDateTime.now());
        
        blacklistCache.put(ip, entry);
        ruleRepository.saveBlacklist(entry);
        log.warn("IP {} 已被添加到永久黑名单,原因: {}", ip, reason);
    }

    public void addToWhitelist(String ip, String description) {
        FirewallWhitelist entry = new FirewallWhitelist();
        entry.setIp(ip);
        entry.setDescription(description);
        entry.setAddedAt(LocalDateTime.now());
        
        whitelistCache.put(ip, entry);
        ruleRepository.saveWhitelist(entry);
        log.info("IP {} 已被添加到白名单,描述: {}", ip, description);
    }

    private void startCleanupTask() {
        // 定时清理任务已通过@Scheduled注解实现
    }
}
  1. 拦截器(增强版)
package com.icoderoad.firewall.interceptor;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.icoderoad.firewall.core.RuleManager;
import com.icoderoad.firewall.model.FirewallRule;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class FirewallInterceptor implements HandlerInterceptor {

    @Autowired
    private RuleManager ruleManager;

    private final Cache<String, AtomicInteger> qpsCache = CacheBuilder.newBuilder()
            .expireAfterWrite(1, TimeUnit.SECONDS)
            .build();

    private final Cache<String, AtomicInteger> userHourlyCache = CacheBuilder.newBuilder()
            .expireAfterWrite(1, TimeUnit.HOURS)
            .build();

    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
        String ip = getClientIp(req);
        String path = req.getRequestURI();

        // 白名单检查
        if (ruleManager.isWhitelisted(ip)) {
            return true;
        }

        // 黑名单检查
        if (ruleManager.isBlacklisted(ip)) {
            resp.sendError(403, "IP已被封禁");
            log.warn("拦截黑名单IP访问: {} -> {}", ip, path);
            return false;
        }

        // 获取匹配规则
        FirewallRule rule = ruleManager.getMatchingRule(path);
        if (rule == null || !rule.isEnabled()) {
            return true; // 无规则或规则未启用,直接放行
        }

        // QPS检查
        if (!checkQps(ip, path, rule)) {
            ruleManager.blockIp(ip, 5, "QPS超限:" + path);
            resp.sendError(429, "访问过于频繁,已被临时封禁");
            log.warn("QPS超限拦截: {} -> {}", ip, path);
            return false;
        }

        // 小时级频率检查
        if (!checkHourlyRate(ip, rule)) {
            ruleManager.blockIp(ip, 10, "小时请求超限:" + path);
            resp.sendError(429, "请求次数超限,已被临时封禁");
            log.warn("小时请求超限拦截: {} -> {}", ip, path);
            return false;
        }

        return true;
    }

    private boolean checkQps(String ip, String path, FirewallRule rule) {
        if (rule.getMaxQps() <= 0) return true;
        
        String key = "qps:" + ip + ":" + path;
        try {
            AtomicInteger count = qpsCache.get(key, () -> new AtomicInteger(0));
            return count.incrementAndGet() <= rule.getMaxQps();
        } catch (Exception e) {
            log.error("QPS检查异常", e);
            return true;
        }
    }

    private boolean checkHourlyRate(String ip, FirewallRule rule) {
        if (rule.getMaxRequestsPerHour() <= 0) return true;
        
        String key = "hourly:" + ip;
        try {
            AtomicInteger count = userHourlyCache.get(key, () -> new AtomicInteger(0));
            return count.incrementAndGet() <= rule.getMaxRequestsPerHour();
        } catch (Exception e) {
            log.error("小时频率检查异常", e);
            return true;
        }
    }

    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;
    }
}
  1. 规则存储接口
package com.icoderoad.firewall.repository;

import java.util.List;

import com.icoderoad.firewall.model.FirewallBlacklist;
import com.icoderoad.firewall.model.FirewallRule;
import com.icoderoad.firewall.model.FirewallWhitelist;

public interface RuleRepository {
    List<FirewallRule> loadRules();
    List<FirewallBlacklist> loadBlacklists();
    List<FirewallWhitelist> loadWhitelists();
    void saveBlacklist(FirewallBlacklist blacklist);
    void saveWhitelist(FirewallWhitelist whitelist);
    void saveRule(FirewallRule rule);
}
  1. 基于JSON文件的规则存储实现
package com.icoderoad.firewall.repository.impl;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

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

import com.fasterxml.jackson.databind.ObjectMapper;
import com.icoderoad.firewall.model.FirewallBlacklist;
import com.icoderoad.firewall.model.FirewallRule;
import com.icoderoad.firewall.model.FirewallWhitelist;
import com.icoderoad.firewall.repository.RuleRepository;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Repository
public class JsonRuleRepository implements RuleRepository {

    @Value("${firewall.rules.file:firewall-rules.json}")
    private String rulesFile;
    
    @Value("${firewall.blacklist.file:firewall-blacklist.json}")
    private String blacklistFile;
    
    @Value("${firewall.whitelist.file:firewall-whitelist.json}")
    private String whitelistFile;

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public List<FirewallRule> loadRules() {
        try {
            String content = new String(Files.readAllBytes(Paths.get(rulesFile)));
            return objectMapper.readValue(content, 
                objectMapper.getTypeFactory().constructCollectionType(List.class, FirewallRule.class));
        } catch (IOException e) {
            log.warn("无法加载规则文件,使用默认规则: {}", e.getMessage());
            return getDefaultRules();
        }
    }

    @Override
    public List<FirewallBlacklist> loadBlacklists() {
        try {
            String content = new String(Files.readAllBytes(Paths.get(blacklistFile)));
            return objectMapper.readValue(content, 
                objectMapper.getTypeFactory().constructCollectionType(List.class, FirewallBlacklist.class));
        } catch (IOException e) {
            log.warn("无法加载黑名单文件: {}", e.getMessage());
            return new ArrayList<>();
        }
    }

    @Override
    public List<FirewallWhitelist> loadWhitelists() {
        try {
            String content = new String(Files.readAllBytes(Paths.get(whitelistFile)));
            return objectMapper.readValue(content, 
                objectMapper.getTypeFactory().constructCollectionType(List.class, FirewallWhitelist.class));
        } catch (IOException e) {
            log.warn("无法加载白名单文件: {}", e.getMessage());
            return new ArrayList<>();
        }
    }

    @Override
    public void saveBlacklist(FirewallBlacklist blacklist) {
        try {
            List<FirewallBlacklist> blacklists = loadBlacklists();
            blacklists.removeIf(bl -> bl.getIp().equals(blacklist.getIp()));
            blacklists.add(blacklist);
            
            String content = objectMapper.writeValueAsString(blacklists);
            Files.write(Paths.get(blacklistFile), content.getBytes());
        } catch (IOException e) {
            log.error("保存黑名单失败: {}", e.getMessage());
        }
    }

    @Override
    public void saveWhitelist(FirewallWhitelist whitelist) {
        try {
            List<FirewallWhitelist> whitelists = loadWhitelists();
            whitelists.removeIf(wl -> wl.getIp().equals(whitelist.getIp()));
            whitelists.add(whitelist);
            
            String content = objectMapper.writeValueAsString(whitelists);
            Files.write(Paths.get(whitelistFile), content.getBytes());
        } catch (IOException e) {
            log.error("保存白名单失败: {}", e.getMessage());
        }
    }

    @Override
    public void saveRule(FirewallRule rule) {
        try {
            List<FirewallRule> rules = loadRules();
            rules.removeIf(r -> r.getPattern().equals(rule.getPattern()));
            rules.add(rule);
            
            String content = objectMapper.writeValueAsString(rules);
            Files.write(Paths.get(rulesFile), content.getBytes());
        } catch (IOException e) {
            log.error("保存规则失败: {}", e.getMessage());
        }
    }

    private List<FirewallRule> getDefaultRules() {
        List<FirewallRule> defaultRules = new ArrayList<>();
        
        // 默认API保护规则
        FirewallRule apiRule = new FirewallRule();
        apiRule.setPattern("/api/.*");
        apiRule.setMaxQps(100);
        apiRule.setMaxRequestsPerHour(1000);
        apiRule.setEnabled(true);
        apiRule.setDescription("API接口默认保护规则");
        defaultRules.add(apiRule);
        
        // 登录接口特殊保护
        FirewallRule loginRule = new FirewallRule();
        loginRule.setPattern("/api/auth/login");
        loginRule.setMaxQps(10);
        loginRule.setMaxRequestsPerHour(100);
        loginRule.setEnabled(true);
        loginRule.setDescription("登录接口防暴力破解");
        defaultRules.add(loginRule);
        
        return defaultRules;
    }
}
  1. 管理控制器(增强版)
package com.icoderoad.firewall.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.icoderoad.firewall.core.RuleManager;
import com.icoderoad.firewall.model.DynamicBlacklistEntry;
import com.icoderoad.firewall.model.FirewallBlacklist;
import com.icoderoad.firewall.model.FirewallRule;
import com.icoderoad.firewall.model.FirewallWhitelist;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequestMapping("/api/firewall/admin")
public class FirewallAdminController {

    @Autowired
    private RuleManager ruleManager;

    @GetMapping("/dynamic-blacklist")
    public List<DynamicBlacklistEntry> getDynamicBlacklist() {
        return ruleManager.getDynamicBlacklist();
    }

    @DeleteMapping("/dynamic-blacklist/{ip}")
    public ResponseEntity<?> removeFromDynamicBlacklist(@PathVariable String ip) {
        ruleManager.removeDynamicBlacklist(ip);
        return ResponseEntity.ok("已移除动态黑名单: " + ip);
    }

    @PostMapping("/blacklist")
    public ResponseEntity<?> addToPermanentBlacklist(
            @RequestParam String ip, 
            @RequestParam(defaultValue = "手动添加") String reason) {
        ruleManager.addToPermanentBlacklist(ip, reason);
        return ResponseEntity.ok("已添加到永久黑名单: " + ip);
    }

    @PostMapping("/whitelist")
    public ResponseEntity<?> addToWhitelist(
            @RequestParam String ip, 
            @RequestParam(defaultValue = "手动添加") String description) {
        ruleManager.addToWhitelist(ip, description);
        return ResponseEntity.ok("已添加到白名单: " + ip);
    }

    @PostMapping("/block-ip")
    public ResponseEntity<?> blockIpTemporarily(
            @RequestParam String ip, 
            @RequestParam int minutes,
            @RequestParam(defaultValue = "手动临时封禁") String reason) {
        ruleManager.blockIp(ip, minutes, reason);
        return ResponseEntity.ok("IP已临时封禁: " + ip + ", 时长: " + minutes + "分钟");
    }

    @PostMapping("/reload-rules")
    public ResponseEntity<?> reloadRules() {
        ruleManager.loadRules();
        ruleManager.loadBlacklists();
        ruleManager.loadWhitelists();
        return ResponseEntity.ok("规则已重新加载");
    }

    @GetMapping("/stats")
    public ResponseEntity<?> getStats() {
        return ResponseEntity.ok().body(
            "动态黑名单数量: " + ruleManager.getDynamicBlacklist().size()
        );
    }
}
  1. 配置类
package com.icoderoad.firewall.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.icoderoad.firewall.interceptor.FirewallInterceptor;

import lombok.RequiredArgsConstructor;

@Configuration
@EnableScheduling
@RequiredArgsConstructor
public class FirewallConfig implements WebMvcConfigurer {

    private final FirewallInterceptor firewallInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(firewallInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/api/firewall/admin/**");
    }
}

配置文件示例
application.yml:

# 防火墙配置
firewall:
  rules:
    file: config/firewall-rules.json
  blacklist:
    file: config/firewall-blacklist.json
  whitelist:
    file: config/firewall-whitelist.json

日志配置

logging:
  level:
    com.icoderoad.firewall: DEBUG
防火墙规则文件示例 (firewall-rules.json):

json
[
  {
    "pattern": "/api/.*",
    "maxQps": 100,
    "maxRequestsPerHour": 1000,
    "enabled": true,
    "description": "API接口默认保护规则"
  },
  {
    "pattern": "/api/auth/.*",
    "maxQps": 20,
    "maxRequestsPerHour": 200,
    "enabled": true,
    "description": "认证接口保护规则"
  },
  {
    "pattern": "/api/admin/.*",
    "maxQps": 50,
    "maxRequestsPerHour": 500,
    "enabled": true,
    "description": "管理接口保护规则"
  }
]

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

❀͜͡傀儡师

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值