当下主流的web服务都做了前后端分离处理,前端和后端之间只需定义好通信的API接口,各自按照restful规范进行业务开发,大大降低了需求开发的周期,但数据表单校验也成为必不可少的安全处理流程。
事实上,我之前负责维护的一个后端微服务就出现测试人员通过API调用时,传入错误数据,导致后端服务数据异常的案例。因此,抽空学习了validator第三方数据校验库。这个库的使用方法网上有很多,这里我只记录一下结合实际echo框架的一些使用场景。
1、自定义字段级别的数据校验
使用场景: 结构体Job中含有的Report字段类型是一个自定义的数据类型(本质是个string数组),正常场景只接收 “xlsx” 和 “html” 这两个字符串。如果需要对这个自定义的字段添加校验函数,方法如下:
type Job struct {ID uuid.UUIDName stringReport pq.StringArray}func TaskReportValidation(fl validator.FieldLevel) bool {reportTypes := fl.Field().Interface().(pq.StringArray)for _, val := range reportTypes {if val != "xlsx" && val != "html" {return false}}return true}
2、自定义结构体级别的数据校验
使用场景: model包中有个结构体Scene,该结构体中的字段大多是自定义的,如果需要对这些字段进行数据校验,可以一个个编写字段级别的校验函数(有点麻烦),也可以对Scene结构体整体进行校验。方法如下:
func SceneStructureValidation(sl validator.StructLevel) {// get scene instancescene := sl.Current().Interface().(model.Scene)// scene实例中需要校验的字段,需要自行编写校验逻辑...}
3、将validator集成到echo中
echo本身没有实现输入数据校验的功能,但是提供了一个校验接口,我们只需实现echo提供的接口即可。
type CustomValidate struct {once sync.Oncevalidator *validator.Validate}// 实现 echo 提供的接口 Validatefunc (c *CustomValidate) Validate(i interface{}) error {c.lazyInit()return c.validate.Struct(i)}// 因为 validator.Validate 实例化做了不少事,这里使用sync.Once将实例化推迟到使用时。func (c *CustomValidate) lazyInit() {c.once.Do(func() {c.validator = validator.New()// 注册 TaskReportValidation_ = c.validator.RegisterValidation("check_report_type", TaskReportValidation)// 注册 SceneStructureValidationc.validator.RegisterStructValidation(SceneStructureValidation, model.Scene)})}// ==== 与echo集成e := echo.New()e.Validator = &CustomValidate{}// 之后就可以在需要进行表单校验的地方通过 ctx.Validate() 进行校验。
参考文章
1. validator官方使用手册
2. 自定义validator,进行输入校验
3. Go 每日一库之 validator
