Iris 中 binding 标签需配合 app.Validator = validator.New() 才生效,否则静默跳过;结构体字段须首字母大写且含 json tag;路由宏如 {id:uint64} 在匹配阶段硬校验,未注册自定义宏将被忽略;URLParam 和 FormValue 需手动校验,ReadJSON 不校验缺失 key。

ReadJSON + binding 标签必须配 app.Validator 才生效
不初始化 validator 实例,binding:"required" 这类标签就完全没用——Iris 不会报错,也不会提示,只是静默跳过校验。你看到的“空字符串通过了校验”,大概率是这个原因。
实操要点:
-
app.Validator = validator.New()必须在iris.New()之后、app.Listen()之前调用,且只能赋值一次 - 结构体字段必须首字母大写(导出),否则
ctx.ReadJSON()绑定失败,字段始终为零值 -
json:"field"tag 不可省略,否则 JSON 字段名无法映射,绑定后字段为空 - 错误类型是
validator.ValidationErrors,别直接err.Error()返回前端,建议用err.(validator.ValidationErrors).Translate(trans)提取可读提示
{id:uint64} 这类路由宏在匹配阶段就拦截非法值
请求 /user/abc 却进了 handler?说明你只写了 /user/{id},没加类型宏。Iris 的路由宏不是装饰器,是 radix tree 匹配时的硬规则——不满足直接 404,根本不会走到你的代码里。
常见陷阱:
-
{id:uint64}拦不住负数字符串(如-1),因为 uint64 解析失败会返回 0,但匹配仍成功;要用{id:int min(1)}或自定义宏 - 自定义宏(如
{oid:int min(1) max(999999)})必须调app.Macros().Register注册,否则整个宏被忽略 -
{path:path}不做 URL 解码,%20还是%20,需手动url.PathUnescape() - 大小写敏感:
{ID}和{id}是两个参数,拼错名会导致ctx.Params().Get("ID")返回空字符串,不易察觉
ctx.URLParam() 和 ctx.FormValue() 没自动校验,必须手动处理
查询参数(?page=2&sort=name)和表单字段(application/x-www-form-urlencoded)不走结构体绑定,Iris 默认不做任何类型或范围检查。你拿到的永远是字符串,转整型、判空、限范围都得自己来。
安全做法:
- 用
ctx.URLParamInt("page")而非strconv.Atoi(ctx.URLParam("page")),前者返回明确 error,后者 panic -
ctx.FormValue("email")可能是空字符串,binding:"email"对它无效,得手动调validator.IsEmail() - 分页场景下,
page小于 1、size为 0 或负数,必须显式拦截,否则可能查全表 - 多个参数依赖关系(如
start_time必须早于end_time)无法靠 tag 表达,得在 handler 里写 if 判断
中间件里做通用参数校验容易绕过且难维护
在中间件里写一堆 if ctx.Path() == "/api/users" && ctx.Method() == "POST" 做校验,看似统一,实则脆弱:新路由漏加判断、宏没配导致参数进来了却没被中间件捕获、多个中间件重复解析 JSON 浪费 CPU。
真正该做的:
- 路由层用宏卡死路径参数(
{id:uint64})——最轻量、最早期拦截 - 请求体用
ReadJSON+ 结构体 binding —— 类型安全、字段级可控 - Controller 内对
ctx.URLParam()和ctx.FormValue()做最小必要校验 —— 明确知道哪些参数需要业务规则约束 - 中间件只做身份认证(JWT)、日志、限流等与参数无关的横切逻辑
最容易被忽略的是:结构体字段即使加了 binding:"required",如果 JSON 中压根没传这个 key,Iris 也不会报错——它只校验“传了但为空”的情况。业务关键字段(比如创建用户时的 email)必须确认 key 存在,不能只靠 binding。











