系统架构设计
- 防火墙配置类
@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);
}
}
- 配置文件类
@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";
}
- 黑名单管理器
@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();
}
}
- 请求过滤器
@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));
}
}
- 管理控制器
@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");
}
}
- 安全配置
@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界面方便管理
第二种方式
- 动态黑名单实体类
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);
}
}
- 防火墙规则实体类
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;
}
- 规则管理器(增强版)
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注解实现
}
}
- 拦截器(增强版)
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;
}
}
- 规则存储接口
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);
}
- 基于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;
}
}
- 管理控制器(增强版)
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()
);
}
}
- 配置类
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": "管理接口保护规则"
}
]