beego filter中需用maxbytesreader限制长度并缓存请求体,再手动解析脱敏,避免破坏后续controller绑定。

Beego 的拦截器(Filter)本身不提供请求/响应体自动解析能力,直接在 Filter 里做 JSON 脱敏必须手动读取、解析、修改、重写 r.Body,否则会破坏后续 Controller 的数据绑定。
Beego Filter 中如何安全读取并脱敏 POST/PUT 请求体
Beego 的 FilterFunc 接收的是 *context.Context,其 ctx.Request 是标准 *http.Request。而 http.Request.Body 是单次可读的 io.ReadCloser —— 一旦被 io.ReadAll 消费,后续 Controller 调用 ctx.Input.JSON() 或 ctx.ParseForm() 就会失败或返回空值。
正确做法是:
- 先用
http.MaxBytesReader包装原始Body,限制最大读取长度(如10 ),防 OOM - 调用
io.ReadAll读出原始字节,得到[]byte - 用
bytes.NewReader创建新ReadCloser,赋值给ctx.Request.Body - 同步更新
ctx.Request.ContentLength和ctx.Request.Header.Set("Content-Length", ...) - 对读出的
[]byte做结构化解析:若Content-Type是application/json,用json.Unmarshal解为map[string]interface{},递归遍历 key 是否命中敏感字段(如"password"、"idCard"、"phone"),仅对字符串类型 value 替换为"***" - 最后用
json.Marshal写回日志或调试输出(注意:不改写原始 Body 字节,只用于记录)
GET 请求参数和 URL 查询串的脱敏时机与方式
GET 请求没有请求体,但敏感信息常出现在 r.URL.Query() 或路径中(如 /api/user/123?token=abc)。脱敏不能只靠字符串匹配,要结合路径和参数名动态判断:
- 用
ctx.Input.Query("token")获取单个参数,或ctx.Request.URL.Query()得到全部url.Values - 对每个 key 检查是否在预设敏感键集合中(支持正则,如
^.*key$、^(pwd|auth|secret)) - 脱敏后需调用
ctx.Request.URL.RawQuery = query.Encode()同步更新原始查询串,否则日志里仍显示明文 - 路径中的 ID 类参数(如
/user/{id})一般不脱敏,但若路径含/reset?code=xxx这类一次性凭证,则需识别并替换 - 不要对整个
RawQuery做正则全局替换 —— 容易误杀非敏感字段(如status=active&token=xxx中只应动token)
Beego Filter 里脱敏逻辑该放在 BeforeRouter 还是 AfterExec
Beego 的 Filter 执行阶段分 BeforeRouter、AfterExec 等。数据脱敏必须在 Controller 执行前完成,且不能干扰路由匹配,所以只能选 BeforeRouter:
-
BeforeRouter:请求刚进入,路由尚未匹配,此时可安全读取并重写Body和URL;Controller 绑定逻辑后续才触发 -
AfterExec:Controller 已执行完毕,响应已生成,此时再脱敏响应体已晚;且无法修改入参 - 别用
FinishRouter—— 它在渲染视图后执行,对 API 接口无意义 - 注册时明确指定:
beego.InsertFilter("/api/*", beego.BeeApp.BeforRouter, yourSanitizeFilter)
为什么不能在 Controller 里用 ctx.Input.Bind 后再脱敏
因为 ctx.Input.Bind 和 ctx.Input.JSON() 底层都依赖 r.Body 流,一旦你在 Filter 里没重置 Body,这些方法就拿不到数据;而如果在 Controller 里自己再读一次 Body,就会导致 Bind 失败,出现空结构体或 panic。
更关键的是:脱敏不是为了“让 Controller 看不见”,而是为了“不让日志、审计、链路追踪看到明文”。如果只在 Controller 层处理,日志中间件(比如基于 BeforeRouter 的)依然会记录原始请求体 —— 这就完全失去了脱敏意义。
真正容易被忽略的一点:Beego 的 GlobalSessions 默认不自动解析 session,如果你的脱敏规则依赖用户角色(比如管理员可看明文),必须在 Filter 开头显式调用 beego.GlobalSessions.SessionStart() 并从 session 取权限,否则所有请求都走同一套脱敏策略。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











