Iris框架中加密响应体须替换底层ResponseWriter实现hook,不能直接操作Body;需按路径注册、校验Content-Type为application/json、用唯一IV加密并Base64编码,且需规避Gzip冲突。

中间件里不能直接加密响应体,得在 WriteHeader/Write 时拦截
Iris 的 ctx.ResponseWriter() 是一个包装过的 http.ResponseWriter,但它的 Write 和 WriteHeader 方法默认不支持 hook。想加密响应数据,必须用 ctx.Response().ResetWriter 替换底层 writer,自己实现带加密逻辑的 ResponseWriter 接口。别试图在中间件末尾读取 ctx.Response().Body() —— 它是只写的缓冲区,且已写入网络栈前无法回溯。
加密中间件必须注册在路由匹配之后、handler 执行之前
用 app.Use(encryptMiddleware) 全局注册会覆盖所有响应,包括静态文件和健康检查;更合理的是按路径控制,比如:
api := app.Party("/api")api.Use(encryptMiddleware)api.Get("/user", userHandler)
注意:如果 handler 里用了 ctx.StopExecution()(如鉴权失败),加密中间件仍会执行——所以加密逻辑开头要判断状态码是否为 2xx,否则跳过。否则可能把 {"error":"unauthorized"} 也加密后返回,前端根本没法解析错误。
加密前必须确保 Content-Type 是 application/json
不是所有响应都该加密。常见踩坑点:
- 前端发了
Accept: text/html,但 handler 调了ctx.HTML()→ 不加密,否则浏览器渲染乱码 - 接口返回 CSV 或图片二进制 → 加密后 MIME 类型不变,但内容已损坏
-
ctx.JSON()自动设Content-Type: application/json,可作为安全判断依据;但若手动ctx.ResponseWriter().Header().Set("Content-Type", "application/json"),需额外校验
推荐判断方式:ct := ctx.GetContentType(); if !strings.HasPrefix(ct, "application/json") { ctx.Next(); return }
AES 加密响应体要注意 IV 传递和 Base64 编码
加密后不能直接写原始字节,HTTP 响应体必须是合法 UTF-8 或二进制流,而 AES 输出是随机字节。必须做两件事:
- 每次加密用唯一 IV(如
cipher.NewGCM(aes).NonceSize()随机生成),IV 和密文一起传给前端 - 最终响应体用 Base64 编码,例如:
base64.StdEncoding.EncodeToString(append(iv, ciphertext...))
别用固定 IV(如全零),否则相同原文永远生成相同密文,存在统计分析风险;也别把 IV 放 header 里——跨域时可能被拦截,统一塞进响应体最稳妥。前端解密时先 Base64 解码,再拆出前 12 字节为 IV,剩余为密文。
真正容易被忽略的是:加密中间件必须兼容 Gzip。如果同时启用了 iris.Compression,加密要在压缩之后做,否则压缩率暴跌;但 Iris 的中间件顺序是线性的,无法自动调整。解决方案是——别用 iris.Compression,改用自定义 writer 同时做压缩+加密,或者干脆放弃压缩,毕竟加密后数据熵值高,Gzip 基本无效。


















