2026/4/2 20:38:01
网站建设
项目流程
做网站的流程方法,新增病例最新消息,什么是关键词搜索,广告投放平台主要有哪些#x1f449; 这是一个或许对你有用的社群#x1f431; 一对一交流/面试小册/简历优化/求职解惑#xff0c;欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料#xff1a; 《项目实战#xff08;视频#xff09;》#xff1a;从书中学#xff0c;往事上…这是一个或许对你有用的社群 一对一交流/面试小册/简历优化/求职解惑欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料《项目实战视频》从书中学往事上“练”《互联网高频面试题》面朝简历学习春暖花开《架构 x 系统设计》摧枯拉朽掌控面试高频场景题《精进 Java 学习指南》系统学习互联网主流技术栈《必读 Java 源码专栏》知其然知其所以然这是一个或许对你有用的开源项目国产Star破10w的开源项目前端包括管理后台、微信小程序后端支持单体、微服务架构RBAC权限、数据权限、SaaS多租户、商城、支付、工作流、大屏报表、ERP、CRM、AI大模型、IoT物联网等功能多模块https://gitee.com/zhijiantianya/ruoyi-vue-pro微服务https://gitee.com/zhijiantianya/yudao-cloud视频教程https://doc.iocoder.cn【国内首批】支持 JDK17/21SpringBoot3、JDK8/11Spring Boot2双版本来源风象南1. 背景与痛点2. 设计思路3. 技术选型4. 核心实现5. 前端控制台6. 配置文件7. 实战应用场景总结1. 背景与痛点在做后端开发时我们常常会遇到这样的困境接口被恶意刷流量比如某个查询接口被短时间大量调用数据库连接数打满最终拖垮整个服务。缺少细粒度防护能力很多系统只有粗糙的全局限流但某些高价值 API比如下单、支付、导出并没有单独保护一旦被攻击影响范围很大。风控策略难以落地规则写死在代码里每次调整都要改代码、打包、上线运维成本高。黑白名单管理混乱一些临时封禁规则放在 Nginx一些写在数据库开发、运维、测试之间没有统一入口。很多企业会引入API 网关如 Kong、Spring Cloud Gateway、NginxLua来解决但这类方案往往过于“重量级”需要额外维护一层组件增加了部署复杂度。 学习和使用成本高不适合中小团队快速落地。 对于单机部署或内网小系统来说显得“杀鸡用牛刀”。因此一个非常现实的需求出现了在 Spring Boot 应用中内嵌一个轻量级 API 防火墙做到单机级别的限流 风控 在线配置无需依赖网关也能快速解决安全与稳定性问题。基于 Spring Boot MyBatis Plus Vue Element 实现的后台管理系统 用户小程序支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能项目地址https://github.com/YunaiV/ruoyi-vue-pro视频教程https://doc.iocoder.cn/video/2. 设计思路目标在SpringBoot 内嵌一层防护层对所有 API 请求进行“前置检查”。核心能力拆解黑白名单支持配置IP白名单、黑名单白名单优先级更高。限流策略- QPS 限流如单接口每秒不超过 100 次请求。 - 时间窗限流如同一用户 1 分钟不超过 60 次调用。 - 突发流量控制避免短时间内瞬时压垮系统。风控规则支持基于时间窗口的访问频率控制如单个IP在60秒内最多访问10次。在线配置提供前端控制台实时修改规则立即生效无需重启。低侵入性以Interceptor或Filter形式接入不影响现有业务逻辑。架构示意┌────────────────────┐ │ API Firewall │ ← 拦截层黑白名单 / 限流 / 风控 └────────────────────┘ ↓ ┌────────────────────┐ │ 应用业务 API │ └────────────────────┘基于 Spring Cloud Alibaba Gateway Nacos RocketMQ Vue Element 实现的后台管理系统 用户小程序支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能项目地址https://github.com/YunaiV/yudao-cloud视频教程https://doc.iocoder.cn/video/3. 技术选型Spring Boot Interceptor最适合做请求前置校验侵入性低。Guava Cache实现高性能内存缓存支持过期策略和并发访问也可使用Caffeine。AtomicInteger 时间窗口基于计数器的限流实现简单高效。Spring Boot Actuator提供健康检查和监控端点。前端页面Tailwind CSS Chart.js现代化响应式管理界面。对于分布式场景后续可以扩展 Redis Lua 实现统一限流但在本文场景下先聚焦单机轻量化防护。4. 核心实现4.1 定义规则实体Data NoArgsConstructor AllArgsConstructor Builder publicclassFirewallRule { /** * 主键ID */ private Long id; /** * 规则名称 */ private String ruleName; /** * API路径匹配模式 */ private String apiPattern; /** * QPS限制每秒最大请求数 */ private Integer qpsLimit; /** * 单用户时间窗限制分钟内最大请求数 */ private Integer userLimit; /** * 时间窗口秒 */ private Integer timeWindow; /** * 是否启用 */ private Boolean enabled; /** * 规则描述 */ private String description; /** * 创建时间 */ private LocalDateTime createdTime; /** * 更新时间 */ private LocalDateTime updatedTime; /** * 检查API路径是否匹配此规则 * * param apiPath API路径 * return 是否匹配 */ publicbooleanmatches(String apiPath) { if (apiPattern null || apiPath null) { returnfalse; } // 支持通配符匹配 Stringpattern apiPattern.replace(**, .*).replace(*, [^/]*); return apiPath.matches(pattern); } }4.2 规则管理器Slf4j Service publicclassRuleManager { Autowired private FirewallRuleMapper ruleMapper; Autowired private FirewallBlacklistMapper blacklistMapper; Autowired private FirewallWhitelistMapper whitelistMapper; /** * 规则缓存 */ privatefinal MapString, FirewallRule ruleCache newConcurrentHashMap(); /** * 黑名单缓存 */ privatefinal MapString, FirewallBlacklist blacklistCache newConcurrentHashMap(); /** * 白名单缓存 */ privatefinal MapString, FirewallWhitelist whitelistCache newConcurrentHashMap(); /** * 初始化加载规则 */ PostConstruct publicvoidinit() { log.info(初始化防火墙规则管理器...); refreshRules(); refreshBlacklist(); refreshWhitelist(); log.info(防火墙规则管理器初始化完成加载规则: {}, 黑名单: {}, 白名单: {}, ruleCache.size(), blacklistCache.size(), whitelistCache.size()); } /** * 获取匹配指定API路径的规则 * * param apiPath API路径 * return 匹配的规则如果没有匹配则返回null */ public FirewallRule getMatchingRule(String apiPath) { if (apiPath null) { returnnull; } // 优先精确匹配 FirewallRuleexactMatch ruleCache.get(apiPath); if (exactMatch ! null exactMatch.isEffectiveEnabled()) { return exactMatch; } // 模式匹配 for (FirewallRule rule : ruleCache.values()) { if (rule.isEffectiveEnabled() rule.matches(apiPath)) { return rule; } } returnnull; } /** * 检查IP是否在黑名单中 * * param ipAddress IP地址 * return 是否在黑名单中 */ publicbooleanisBlacklisted(String ipAddress) { if (ipAddress null) { returnfalse; } for (FirewallBlacklist blacklist : blacklistCache.values()) { if (blacklist.isValid() blacklist.matches(ipAddress)) { returntrue; } } returnfalse; } /** * 检查IP是否在白名单中 * * param ipAddress IP地址 * return 是否在白名单中 */ publicbooleanisWhitelisted(String ipAddress) { if (ipAddress null) { returnfalse; } for (FirewallWhitelist whitelist : whitelistCache.values()) { if (whitelist.isValid() whitelist.matches(ipAddress)) { returntrue; } } returnfalse; } /** * 定时刷新缓存 */ Scheduled(fixedRate 300000)// 每5分钟刷新一次 publicvoidscheduledRefresh() { try { refreshRules(); refreshBlacklist(); refreshWhitelist(); log.debug(定时刷新防火墙规则缓存完成); } catch (Exception e) { log.error(定时刷新防火墙规则缓存失败, e); } } }4.3 拦截器实现逻辑Slf4j Component publicclassFirewallInterceptorimplementsHandlerInterceptor { Autowired private RuleManager ruleManager; Autowired private FirewallService firewallService; Value(${firewall.default.qps-limit:100}) privateint defaultQpsLimit; Value(${firewall.default.user-limit:1000}) privateint defaultUserLimit; Value(${firewall.default.time-window:60}) privateint defaultTimeWindow; /** * QPS限制缓存 - 存储每个IPAPI的访问计数 */ privatefinal CacheString, AtomicInteger qpsCache CacheBuilder.newBuilder() .maximumSize(10000) .expireAfterWrite(1, TimeUnit.MINUTES) .build(); /** * 用户限制缓存 - 存储每个IP的访问计数 */ privatefinal CacheString, AtomicInteger userCache CacheBuilder.newBuilder() .maximumSize(10000) .expireAfterWrite(1, TimeUnit.HOURS) .build(); Override publicbooleanpreHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception { longstartTime System.currentTimeMillis(); StringipAddress getClientIpAddress(request); StringapiPath request.getRequestURI(); StringuserAgent request.getHeader(User-Agent); Stringmethod request.getMethod(); log.debug(防火墙拦截检查: IP{}, API{}, Method{}, ipAddress, apiPath, method); try { // 1. 检查白名单 if (ruleManager.isWhitelisted(ipAddress)) { log.debug(IP {} 在白名单中允许访问, ipAddress); logAccess(ipAddress, apiPath, userAgent, method, 200, null, startTime); returntrue; } // 2. 检查黑名单 if (ruleManager.isBlacklisted(ipAddress)) { log.warn(IP {} 在黑名单中拒绝访问, ipAddress); blockRequest(response, IP地址被列入黑名单, 403); logAccess(ipAddress, apiPath, userAgent, method, 403, IP黑名单拦截, startTime); returnfalse; } // 3. 获取匹配的防火墙规则 FirewallRulerule ruleManager.getMatchingRule(apiPath); if (rule null) { // 使用默认规则 rule createDefaultRule(apiPath); } // 4. QPS限制检查 if (!checkQpsLimit(ipAddress, apiPath, rule)) { log.warn(IP {} 访问 {} 超过QPS限制 {}, ipAddress, apiPath, rule.getEffectiveQpsLimit()); blockRequest(response, 访问频率过高请稍后再试, 429); logAccess(ipAddress, apiPath, userAgent, method, 429, QPS限制拦截, startTime); returnfalse; } // 5. 用户限制检查 if (!checkUserLimit(ipAddress, rule)) { log.warn(IP {} 超过用户限制 {}, ipAddress, rule.getEffectiveUserLimit()); blockRequest(response, 访问次数超过限制请稍后再试, 429); logAccess(ipAddress, apiPath, userAgent, method, 429, 用户限制拦截, startTime); returnfalse; } // 6. 记录正常访问 logAccess(ipAddress, apiPath, userAgent, method, 200, null, startTime); log.debug(IP {} 访问 {} 通过防火墙检查, ipAddress, apiPath); returntrue; } catch (Exception e) { log.error(防火墙拦截器处理异常: IP{}, API{}, ipAddress, apiPath, e); logAccess(ipAddress, apiPath, userAgent, method, 500, 系统异常, startTime); returntrue; // 异常情况下允许通过避免影响正常业务 } } /** * 检查QPS限制 */ privatebooleancheckQpsLimit(String ipAddress, String apiPath, FirewallRule rule) { Stringkey ipAddress : apiPath; intqpsLimit rule.getEffectiveQpsLimit(); if (qpsLimit 0) { returntrue; // 无限制 } AtomicIntegercounter qpsCache.getIfPresent(key); if (counter null) { counter newAtomicInteger(0); qpsCache.put(key, counter); } intcurrentCount counter.incrementAndGet(); return currentCount qpsLimit; } /** * 检查用户限制 */ privatebooleancheckUserLimit(String ipAddress, FirewallRule rule) { intuserLimit rule.getEffectiveUserLimit(); if (userLimit 0) { returntrue; // 无限制 } AtomicIntegercounter userCache.getIfPresent(ipAddress); if (counter null) { counter newAtomicInteger(0); userCache.put(ipAddress, counter); } intcurrentCount counter.incrementAndGet(); return currentCount userLimit; } /** * 获取客户端真实IP地址 */ private String getClientIpAddress(HttpServletRequest request) { StringxForwardedFor request.getHeader(X-Forwarded-For); if (xForwardedFor ! null !xForwardedFor.isEmpty() !unknown.equalsIgnoreCase(xForwardedFor)) { return xForwardedFor.split(,)[0].trim(); } StringxRealIp request.getHeader(X-Real-IP); if (xRealIp ! null !xRealIp.isEmpty() !unknown.equalsIgnoreCase(xRealIp)) { return xRealIp; } return request.getRemoteAddr(); } }4.4 在线配置接口Slf4j RestController RequestMapping(/api/firewall) CrossOrigin(origins *)// 允许跨域访问 publicclassFirewallController { Autowired private RuleManager ruleManager; Autowired private FirewallService firewallService; Autowired private FirewallInterceptor firewallInterceptor; /** * 获取所有防火墙规则 */ GetMapping(/rules) public ResponseEntityListFirewallRule getRules() { try { ListFirewallRule rules ruleManager.getAllRules(); return ResponseEntity.ok(rules); } catch (Exception e) { log.error(获取防火墙规则失败, e); return ResponseEntity.status(500).build(); } } /** * 创建或更新防火墙规则 */ PostMapping(/rules) public ResponseEntityMapString, Object saveRule(RequestBody FirewallRule rule) { MapString, Object result newHashMap(); try { booleansuccess ruleManager.saveRule(rule); if (success) { result.put(success, true); result.put(message, 规则保存成功); return ResponseEntity.ok(result); } else { result.put(success, false); result.put(message, 规则保存失败); return ResponseEntity.status(500).body(result); } } catch (Exception e) { log.error(保存防火墙规则失败, e); result.put(success, false); result.put(message, 系统异常: e.getMessage()); return ResponseEntity.status(500).body(result); } } /** * 删除防火墙规则 */ DeleteMapping(/rules/{id}) public ResponseEntityMapString, Object deleteRule(PathVariable Long id) { MapString, Object result newHashMap(); try { booleansuccess ruleManager.deleteRule(id); if (success) { result.put(success, true); result.put(message, 规则删除成功); return ResponseEntity.ok(result); } else { result.put(success, false); result.put(message, 规则删除失败); return ResponseEntity.status(500).body(result); } } catch (Exception e) { log.error(删除防火墙规则失败, e); result.put(success, false); result.put(message, 系统异常: e.getMessage()); return ResponseEntity.status(500).body(result); } } /** * 获取黑名单列表 */ GetMapping(/blacklist) public ResponseEntityListFirewallBlacklist getBlacklist() { try { ListFirewallBlacklist blacklist ruleManager.getAllBlacklist(); return ResponseEntity.ok(blacklist); } catch (Exception e) { log.error(获取黑名单失败, e); return ResponseEntity.status(500).build(); } } /** * 添加黑名单 */ PostMapping(/blacklist) public ResponseEntityMapString, Object addBlacklist(RequestBody FirewallBlacklist blacklist) { MapString, Object result newHashMap(); try { booleansuccess ruleManager.addBlacklist(blacklist); if (success) { result.put(success, true); result.put(message, 黑名单添加成功); return ResponseEntity.ok(result); } else { result.put(success, false); result.put(message, 黑名单添加失败); return ResponseEntity.status(500).body(result); } } catch (Exception e) { log.error(添加黑名单失败, e); result.put(success, false); result.put(message, 系统异常: e.getMessage()); return ResponseEntity.status(500).body(result); } } /** * 获取访问日志 */ GetMapping(/logs) public ResponseEntityListFirewallAccessLog getLogs( RequestParam(defaultValue 1) int page, RequestParam(defaultValue 20) int size, RequestParam(required false) String ipAddress, RequestParam(required false) String apiPath) { try { ListFirewallAccessLog logs firewallService.getAccessLogs(page, size, ipAddress, apiPath); return ResponseEntity.ok(logs); } catch (Exception e) { log.error(获取访问日志失败, e); return ResponseEntity.status(500).build(); } } /** * 获取统计数据 */ GetMapping(/statistics) public ResponseEntityMapString, Object getStatistics( RequestParamDateTimeFormat(pattern yyyy-MM-dd) LocalDate startDate, RequestParamDateTimeFormat(pattern yyyy-MM-dd) LocalDate endDate) { try { MapString, Object statistics firewallService.getStatistics(startDate, endDate); return ResponseEntity.ok(statistics); } catch (Exception e) { log.error(获取统计数据失败, e); return ResponseEntity.status(500).build(); } } }这样我们就有了一个“可实时更新”的防火墙层。5. 前端控制台一个现代化的管理页面基于HTML5 Tailwind CSS JavaScript提供完整的防火墙管理功能!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleWeb防火墙控制台/title script srchttps://cdn.tailwindcss.com/script link hrefhttps://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css relstylesheet script srchttps://cdn.jsdelivr.net/npm/chart.js/script /head body classbg-gray-50 font-sans div classmin-h-screen !-- 顶部导航栏 -- nav classbg-white shadow-lg border-b border-gray-200 div classmax-w-7xl mx-auto px-4 sm:px-6 lg:px-8 div classflex justify-between h-16 !-- 左侧 Logo 和导航 -- div classflex items-center space-x-8 div classflex items-center space-x-3 div classbg-blue-600 p-2 rounded-lg i classfas fa-shield-alt text-white text-xl/i /div span classtext-xl font-bold text-gray-900Web防火墙/span /div !-- 主导航菜单 -- div classhidden md:flex space-x-4 button classnav-btn active>class FirewallApp { constructor() { this.apiBase /api/firewall; this.currentPage dashboard; this.rules []; this.charts {}; this.init(); } asyncinit() { this.bindEvents(); awaitthis.loadDashboard(); this.startAutoRefresh(); } // 加载仪表盘数据 asyncloadDashboard() { try { const [rules, blacklist, statistics] awaitPromise.all([ this.fetchData(/rules), this.fetchData(/blacklist), this.fetchData(/statistics?startDate this.getDateString(-7) endDate this.getDateString(0)) ]); this.updateDashboardStats(rules, blacklist, statistics); this.updateCharts(statistics); } catch (error) { console.error(加载仪表盘数据失败:, error); } } // 更新统计数据 updateDashboardStats(rules, blacklist, statistics) { document.getElementById(today-requests).textContent statistics.todayRequests || 0; document.getElementById(today-blocked).textContent statistics.todayBlocked || 0; document.getElementById(active-rules).textContent rules.filter(r r.enabled).length; document.getElementById(blacklist-count).textContent blacklist.length; } // 更新图表 updateCharts(statistics) { // 请求趋势图 if (this.charts.requestChart) { this.charts.requestChart.destroy(); } const ctx1 document.getElementById(requestChart).getContext(2d); this.charts.requestChart newChart(ctx1, { type: line, data: { labels: statistics.dates || [], datasets: [{ label: 总请求, data: statistics.requests || [], borderColor: rgb(59, 130, 246), backgroundColor: rgba(59, 130, 246, 0.1), tension: 0.4 }, { label: 被拦截, data: statistics.blocked || [], borderColor: rgb(239, 68, 68), backgroundColor: rgba(239, 68, 68, 0.1), tension: 0.4 }] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: true } } } }); } // 获取数据 asyncfetchData(endpoint) { const response awaitfetch(this.apiBase endpoint); if (!response.ok) { thrownewError(HTTP error! status: ${response.status}); } returnawait response.json(); } // 自动刷新 startAutoRefresh() { setInterval(() { if (this.currentPage dashboard) { this.loadDashboard(); } }, 30000); // 每30秒刷新一次 } } // 初始化应用 newFirewallApp();实时仪表盘显示请求量、拦截数、活跃规则等关键指标可视化图表请求趋势和拦截分布的图表展示规则管理在线添加、修改、删除防火墙规则黑白名单IP地址的黑白名单管理访问日志详细的访问记录和拦截日志6. 配置文件在application.yml中设置完整的防火墙参数server: port:8080 servlet: context-path:/ spring: application: name:springboot-firewall # Jackson配置 jackson: serialization: write-dates-as-timestamps:false time-zone:GMT8 date-format:yyyy-MM-ddHH:mm:ss # 数据源配置 (H2内嵌数据库) datasource: url:jdbc:h2:mem:firewall;DB_CLOSE_DELAY-1;DB_CLOSE_ON_EXITFALSE driver-class-name:org.h2.Driver username:sa password: # H2控制台配置 h2: console: enabled:true path:/h2-console settings: web-allow-others:true # SQL初始化 sql: init: mode:always schema-locations:classpath:schema.sql ># 针对订单接口的特殊规则 -ruleName:订单保护 apiPattern:/api/orders/** qpsLimit:50 userLimit:5 timeWindow:60 enabled:true description: 防止恶意刷单和重复下单内容平台场景# 评论和点赞接口限制 -ruleName:内容互动限制 apiPattern:/api/comments/**,/api/likes/** qpsLimit:200 userLimit:20 timeWindow:300 enabled:true description: 防止垃圾评论和刷赞行为7.2 突发流量应对营销活动期间// 通过API动态调整规则 POST /api/firewall/rules { ruleName: 秒杀活动保护, apiPattern: /api/seckill/**, qpsLimit: 1000, userLimit: 1, timeWindow: 60, enabled: true, description: 秒杀活动期间特殊限制 }爬虫防护// 手动添加黑名单示例 FirewallBlacklist blacklist new FirewallBlacklist(); blacklist.setIpAddress(192.168.1.100); blacklist.setReason(恶意爬虫行为); blacklist.setExpireTime(LocalDateTime.now().plusHours(24)); blacklist.setEnabled(true); ruleManager.addBlacklist(blacklist); log.info(IP {} 已手动加入黑名单, blacklist.getIpAddress());7.3 部署和运维Docker 部署FROM openjdk:11-jre-slim VOLUME /tmp COPY target/springboot-firewall-1.0.jar app.jar EXPOSE 8080 ENTRYPOINT [java,-jar,/app.jar]监控集成# Prometheus 监控指标 management: metrics: tags: application: firewall export: prometheus: enabled: true总结本文实现了一个基于 SpringBoot 的轻量级 API 防火墙通过拦截器机制提供实时防护能力。系统采用 Guava Cache 实现高性能内存缓存支持 QPS 限制和用户访问频率控制。提供了完整的黑白名单管理功能配备现代化的 Web 管理界面支持规则的在线配置和实时生效。整体架构简洁高效适合中小型项目快速集成使用。https://github.com/yuboon/java-examples/tree/master/springboot-firewall欢迎加入我的知识星球全面提升技术能力。 加入方式“长按”或“扫描”下方二维码噢星球的内容包括项目实战、面试招聘、源码解析、学习路线。文章有帮助的话在看转发吧。 谢谢支持哟 (*^__^*