beego filter注册必须在路由匹配前执行,即main.go的init()最开头或app.conf加载后、beego.run()前调用insertfilter;需调用ctx.next()传递控制权,拦截非法请求用ctx.abort(),获取真实ip应解析x-forwarded-for头并校验格式,日志须结构化且避免敏感数据。

Filter注册必须在路由匹配前执行
Beego的InsertFilter默认按注册顺序执行,但关键在于时机:只有在beego.Router或beego.Include调用前注册,才能确保它覆盖所有请求。如果在init()里晚于路由注册,该Filter可能被跳过。
- 正确位置是
main.go的init()函数最开头,或app.conf加载后、beego.Run()前 - 使用
beego.InsertFilter("/*", beego.BeforeRouter, LogFilter)可捕获全部路径;若只针对API,用/api/* - 别用
beego.AfterStatic——它只对非静态资源生效,且晚于路由匹配,日志会漏掉404等错误路径
LogFilter里必须调用ctx.Next()否则请求中断
很多初学者写完日志就返回,忘记继续传递控制权,结果所有请求都卡住,返回空白页或超时。Beego的Filter不是“装饰器”,而是链式调用节点,ctx.Next()才是触发后续Filter或Controller的关键。
-
ctx.Next()必须放在日志记录之后(测耗时)或之前(记入参),不能省略 - 如果想拦截非法请求(如未登录),应在
ctx.Next()前做判断,并手动调用ctx.Abort(401)或ctx.Redirect() - 不要在Filter里
panic或log.Fatal,这会绕过recover机制,直接崩溃goroutine
获取真实客户端IP需检查X-Forwarded-For头
直接读ctx.Request.RemoteAddr拿到的是反向代理(Nginx/ALB)的IP,不是用户真实IP。日志审计若依赖IP做风控或溯源,必须手动解析转发头。
- 优先取
ctx.Request.Header.Get("X-Forwarded-For"),取第一个非空IP(注意逗号分隔) - 若部署在云环境(如阿里云SLB),可能要用
X-Real-IP,需根据实际网关配置调整 - 务必校验IP格式,避免日志注入:
net.ParseIP(ipStr)不为nil再写入 - 敏感系统建议配合
ctx.Input.IP()(Beego v2内置方法),它已做基础信任链判断
结构化日志字段要与业务错误码对齐
审计日志不是只记URL和时间就够了。当线上出问题时,你得能快速关联到具体业务动作、用户身份、操作结果。硬编码字符串日志会让ELK或Prometheus难以聚合分析。
- 至少包含:
method、path、status、duration_ms、user_id(从session或token解析)、trace_id(如有分布式追踪) - 别把整个
ctx.Input.RequestBody打进去——大文件上传或含密码字段会泄露敏感数据 - Beego v2支持
ctx.Input.Data["json"],可用于提取已解析的JSON参数,比手动io.ReadAll安全 - 日志级别建议统一用
log.Info,错误单独走recover中间件,避免混在一起难过滤
recoverpanic中间件+自定义error handler,否则500错误不会出现在你的日志里。











