问题
在日常需求中经常会有更新部分参数的需求,比如一个人的name、age、salary 前端可能只更新age字段,这时候发送的json通常是这样的
{"age":12}
这时候在gin/golang端的验证结构体则是这样的 ``
type UpdateParams struct {
Name string `json:"name" binding:"omitempty,gt=0,lte=50" label:"名字"`
Age int `json:"age" binding:"omitempty,gt=0" label:"年龄"`
Salary int `json:"salary" binding:"omitempty,gt=0" label:"薪水"`
}
但是这样存在的问题就是,如果用户不小心设置成0,数据验证时同样不会报错,因为omitempty标签允许字段为空字符串("")或零值(如0)。虽然age被设置为0,但是被omitempty认为是未设置,所以gt标签根本不会验证。同时age又不能设置成required,所以这样就造成了一定的漏洞。
同样的问题也会发生在name字段,如果前端发送json
{"name":""}
情况和age一样,空字符串也被当做未设置该字段,从而验证通过,造成了漏洞。这个问题在字段少的时候可以通过将每个字段都设置成required来强制前端发送每个字段,但是如果有很多字段就不太现实了。
解决办法
将gin/golang端的结构字段都修改成指针
type UpdateParams struct {
Name *string `json:"name" binding:"omitempty,gt=0,lte=50" label:"名字"`
Age *int `json:"age" binding:"omitempty,gt=0" label:"年龄"`
Salary *int `json:"salary" binding:"omitempty,gt=0" label:"薪水"`
}
解决原理
在Go语言中nil值可以表示“未设置”或“无值”。
-
omitempty标签的含义:- 当字段类型为非指针类型时,
omitempty标签允许字段为空字符串("")或零值(如0),而不是未设置。 - 当字段类型为指针类型时,
omitempty标签允许字段为nil,表示字段未设置。
- 当字段类型为非指针类型时,
-
omitempty标签与指针类型的结合:- 当您使用指针类型时,如果字段未设置(即前端发送的数据中没有这个字段),那么绑定到结构体时,对应的指针字段将会是
nil。 - 如果字段被设置了,那么对应的指针字段将会指向一个非
nil的值,此时该值就能被后面的标签处理了。 - 因此,
omitempty标签可以正确地处理指针类型的字段,区分“未设置”和“设置了但为零值”的情况。
- 当您使用指针类型时,如果字段未设置(即前端发送的数据中没有这个字段),那么绑定到结构体时,对应的指针字段将会是
以上是综合多方搜索之后的结果,各位大佬如果有更好的解决办法、不同的观点,欢迎评论指正。