Beego需在BeforeRouter和BeforeStatic阶段手动解析X-Forwarded-For获取真实IP并校验黑白名单,白名单优先、黑名单调Abort,静态资源需额外过滤,IP提取须校验可信代理网段。

beego.BeforeRouter 里手动解析 IP 并校验黑白名单
Beego 没有内置 IP 黑白名单中间件,必须自己在 beego.BeforeRouter 阶段介入。这个时机最早能拿到完整请求对象,且尚未进入路由匹配或 Controller 初始化,适合做前置拦截。
关键点在于:IP 提取不能只看 c.Ctx.Request.RemoteAddr,要优先检查 X-Forwarded-For(反向代理场景),再 fallback 到 RemoteAddr;校验逻辑必须用预加载的 map 或 set(如 map[string]bool),避免每次查数据库或文件。
- 白名单优先级高于黑名单:命中白名单直接放行,不走后续判断
- 黑名单匹配后必须调
c.Abort(403, "Forbidden"),否则请求继续向下执行 - 不要在过滤器里做耗时操作(如 HTTP 请求、DB 查询),会拖慢所有请求
- 若用 Redis 存黑白名单,建议用
SISMEMBER+EXPIRE控制更新时效,但注意网络延迟可能放大首字节时间
如何正确提取客户端真实 IP
Beego 的 c.Ctx.Request.RemoteAddr 返回的是直连地址,在 Nginx / Cloudflare 后是负载均衡或代理 IP。必须手动解析 X-Forwarded-For 头,并取最左非信任段。
常见错误是直接 strings.Split(header, ",")[0] —— 攻击者可伪造该头。稳妥做法是:配置可信代理网段(如 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16),从右往左剥离可信 IP,剩下一个才是真实客户端 IP。
- 示例代码片段:
func getClientIP(c *context.Context) string { if ip := c.Ctx.Request.Header.Get("X-Forwarded-For"); ip != "" { ips := strings.Split(ip, ",") for i := len(ips) - 1; i >= 0; i-- { ip = strings.TrimSpace(ips[i]) if !isTrustedProxy(ip) { return ip } } } return strings.Split(c.Ctx.Request.RemoteAddr, ":")[0] } -
isTrustedProxy应预编译 CIDR 网段,用net.IPNet.Contains判断,别用字符串匹配 - IPv6 地址需用
net.ParseIP标准化后再比对,避免::1和127.0.0.1被当成不同 IP
黑白名单数据加载与热更新
硬编码在代码里无法动态调整;从配置文件读取又缺乏实时性。推荐方案:启动时从 app.conf 加载初始名单,再通过独立 HTTP 管理端点(如 /admin/ip-whitelist)支持运行时增删,配合原子指针替换。
- 白名单 key 示例:
whitelist_ips = 192.168.1.100,2001:db8::1,用beego.AppConfig.Strings("whitelist_ips")读取 - 黑名单建议存 Redis,key 为
blacklist:ip,值为过期时间戳(便于审计和自动清理) - 热更新时别直接修改 map,用
sync.RWMutex包裹读写,或用atomic.Value替换整个 map 实例 - 每次请求都走 map 查找,O(1);但 map 若过大(>10 万条),要考虑分片或布隆过滤器预检
别漏掉静态资源路径的拦截
Beego 对 /static/ 下的请求默认绕过 beego.BeforeRouter,直接由静态处理器响应 —— 这意味着你写的 IP 拦截对 /static/js/app.js 完全无效。
必须额外注册一个 beego.BeforeStatic 过滤器,复用同一套 IP 校验逻辑。注册路径要严格匹配,比如:
beego.InsertFilter("/static/*", beego.BeforeStatic, ipBlacklistFilter)- 路径模式中
/static/*必须带尾部*,否则只匹配/static目录本身 -
beego.BeforeStatic阶段无法用c.Input.Session,但 IP 提取逻辑完全一致,无需额外适配 - 若同时用了 CDN,需确保 CDN 不缓存 403 响应,否则黑名单生效后用户仍看到旧资源
实际部署时最容易被忽略的是反向代理场景下的 IP 解析一致性,以及静态资源路径的双重过滤覆盖。这两处一旦遗漏,黑白名单就形同虚设。


















