beego 审计日志需在 base controller 的 prepare 方法中统一埋点,禁用 accesslogs,使用独立 json 格式 auditlogger 异步记录脱敏后的 ip、方法、uri、ua 和参数。

Beego 默认不记录用户操作审计日志,必须手动在请求生命周期中注入逻辑;仅靠 logs.SetLogger 配置文件输出或 beego.AccessLogs 开关无法满足审计需求(比如记录谁、何时、做了什么、参数是什么)。
在 Base Controller 的 Prepare 方法里统一埋点
这是最常用也最可控的方式:所有控制器继承自一个 Base 结构体,把审计逻辑写进 Prepare(),确保每次 HTTP 请求都触发。
- 不要用中间件替代——Beego v2 的中间件对
ctx.Input的访问稳定性不如Controller原生方法,尤其在重定向或 panic 后可能丢失关键字段 - 必须调用
s.Ctx.Input.ReadRequest()(若未显式读取 body),否则s.Ctx.Input.RequestBody为空,POST/PUT 参数拿不到 - 避免直接拼接
s.Ctx.Input.Params,它只含路由参数(如:id),不含 query 或 form 数据;要用s.Ctx.Input.Query("key")和s.Ctx.Input.GetString("field") - 敏感字段(如密码、token)必须在写入前过滤,建议用白名单 key 列表做
map[string]bool判断
用 logs.BeeLogger 写结构化审计日志(非 AccessLog)
别混用 beego.Info() 或 logs.Info()——它们走的是通用日志通道,级别和格式难统一。审计日志应独立通道、固定格式、可检索。
- 先创建专用 logger:
auditLogger := logs.NewLogger(10000),再用auditLogger.SetLogger(logs.AdapterFile, `{"filename":"logs/audit.log","level":6}`) - 调用
auditLogger.SetFormatter(&logs.JSONFormatter{})输出 JSON,方便后续用 ELK 或 grep 解析;注意JSONFormatter对中文支持良好,但需确保 Go 环境编码为 UTF-8 - 日志内容至少包含:
time.Now().Format("2006-01-02T15:04:05Z07:00")、s.Ctx.Input.IP()、s.Ctx.Input.Method()、s.Ctx.Request.RequestURI、s.Ctx.Input.UserAgent()、脱敏后的参数 map - 不要在
Prepare()里做耗时操作(如写 DB、发 HTTP),审计日志必须异步或缓冲;可用auditLogger.Async(true)启用 goroutine 写入
绕过 Beego 自动 AccessLog 干扰
Beego 默认开启的 beego.AccessLogs = true(dev 模式下强制 true)会输出一行简短请求日志,和你的审计日志重复且格式不一致,必须关掉。
- 在
main.go中beego.Run()前加:beego.AccessLogs = false - 同时确认没调用
beego.SetLogger("file", ...)—— 这是旧版 API,会干扰logs.BeeLogger实例,导致审计日志被吞或乱序 - 如果用了
logs.Reset(),必须在auditLogger.SetLogger(...)之后再调beego.SetLogger(logs.GetBeeLogger()),否则beego.Run()会覆盖你刚设的 auditLogger - 检查
conf/app.conf中是否残留accesslogs = true,该配置在新版本中已失效,但可能误导人
真正难的不是写进去,而是字段一致性与长期可维护性:IP 可能是代理后的真实 IP(得从 X-Forwarded-For 解析)、UserAgent 解析需第三方库(如 golang-useragent)、参数加密/脱敏规则要随业务演进——这些没法靠框架自动完成,得在 Prepare() 里留好扩展钩子。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











