开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情
简单参数校验
在web程序开发中,参数校验是必不可少的,通过参数校验可以保证请求参数的合法性并且识别恶意请求,参数校验的方法有很多,最简单的方法就是后端接收到参数之后使用if进行判断,当参数不合法时返回异常提示信息,例如在注册页面,需要保证两次输入的密码是否一致等。
这种参数校验是最简单直接的,同时也是最繁琐最破坏代码的,毕竟谁也不想在写逻辑之前还要写大串大串的if来校验参数。
validator
在使用validator库之前需要先导入:
go get github.com/go-playground/validator/v10
validator文档:pkg.go.dev/github.com/…
在Gin框架中可以使用validator库来进行参数校验,使用这个库进行校验时,可以避免大串的if,只需要在定义结构体时在binding标签中指定参数的合法范围即可。
代码示例:
type Register struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
RePassword string `json:"re_password" binding:"required,eqfield=Password"`
Email string `json:"email" binding:"required,email"`
Age int `json:"age" binding:"gt=18,lt=60"`
}
func main() {
g := gin.Default()
g.POST("/register", func(c *gin.Context) {
var register Register
err := c.BindJSON(®ister)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "OK",
})
})
err := g.Run(":8888")
if err != nil {
return
}
}
上面代码中模拟了一个注册请求,并且针对所有参数指定了binding标签,标签中的required表示当前参数为必填,如果在请求时没有携带该参数则会报错,email表示该参数格式必须为邮箱格式,gt表示大于,lt表示小于,上面代码中的age参数必须大于18小于60,eqfield=Password表示当前字段的值必须和Password字段的值相同。
可以使用postman或者浏览器直接发送请求进行验证。
常用参数约束如下:
约束 | 说明 | 示例 |
required | 必填 | required |
格式必须是邮箱格式 | ||
eqfield | 指定与某个字段值一样 | eqfield=Password |
ne | 不等于 | ne=5 |
gt | 大于 | gt=18 |
gte | 大于等于 | gte=18 |
lt | 小于 | lt=60 |
lte | 小于等于 | lte=60 |
max | 最大 | max=60 |
min | 最小 | min=18 |
oneof | 只能是指定值中的一个 | oneof=male female |
eq | 等于 | eq=test |
len | 长度 | len=20 |
startswith | 字符串以什么开头 | startswith=hello |
endswith | 字符串以什么结尾 | endswith=world |
contains | 字符串包含子串 | contains=test |
自定义参数校验
上面介绍了Validator中的简单参数校验和常用的约束,但是在开发中,还可能会碰到比较复杂的参数校验,这些情况下使用上述提供的功能就无法完成,就需要我们自己自定义参数校验了,自定义参数校验的方法很简单,具体代码如下:
type Register struct {
Username string `json:"username" binding:"required" validate:"userName"`
Password string `json:"password" binding:"required"`
RePassword string `json:"re_password" binding:"required,eqfield=Password"`
Email string `json:"email" binding:"required,email"`
Age int `json:"age" binding:"gt=18,lt=60"`
}
// 自定义校验函数
func userName(fl validator.FieldLevel) bool {
if fl.Field().String() != "testName" {
return false
}
return true
}
func main() {
g := gin.Default()
// 新建一个validator
validate := validator.New()
g.POST("/register", func(c *gin.Context) {
var register Register
// 将自定义的tag和校验函数注册到validator中,并将两者绑定
err := validate.RegisterValidation("userName", userName)
err = c.BindJSON(®ister)
// 参数校验
err = validate.Struct(register)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "OK",
})
})
err := g.Run(":8888")
if err != nil {
return
}
}
自定义参数校验需要使用到validate标签,并且在标签内自定义一个约束名称,然后需要自定义一个参数校验函数,函数参数为validator.FieldLevel
,通过该参数可以拿到自定义约束字段的值,然后根据是否校验通过返回true或false。
代码中通过validate := validator.New()
新建一个validator,然后调用RegisterValidation将自定义校验注册到validator中,传入自定义约束名称和自定义校验函数,完成两者的绑定,最后在代码中调用Struct方法即可完成参数校验。