package validator import ( "errors" "fmt" "regexp" "strconv" "strings" "time" "github.com/go-playground/validator/v10" ) var validate *validator.Validate // 初始化自定义校验器 func init() { validate = validator.New() if err := validate.RegisterValidation("name", validName); err != nil { panic(fmt.Sprintf("注册 name 验证器时发生错误: %v", err)) } // 注册自定义验证器 validmobile if err := validate.RegisterValidation("mobile", validmobile); err != nil { panic(fmt.Sprintf("注册 mobile 验证器时发生错误: %v", err)) } // 注册自定义验证器 validDate if err := validate.RegisterValidation("date", validDate); err != nil { panic(fmt.Sprintf("注册 date 验证器时发生错误: %v", err)) } // 注册自定义验证器 validIDCard if err := validate.RegisterValidation("idCard", validIDCard); err != nil { panic(fmt.Sprintf("注册 idCard 验证器时发生错误: %v", err)) } if err := validate.RegisterValidation("bankCard", validBankCard); err != nil { panic(fmt.Sprintf("注册 bankCard 验证器时发生错误: %v", err)) } if err := validate.RegisterValidation("USCI", validUSCI); err != nil { panic(fmt.Sprintf("注册 USCI 社会统一信用代码 验证器时发生错误: %v", err)) } if err := validate.RegisterValidation("mobileType", validMobileType); err != nil { panic(fmt.Sprintf("注册 mobileType 验证器时发生错误: %v", err)) } if err := validate.RegisterValidation("password", validatePassword); err != nil { panic(fmt.Sprintf("注册 password 验证器时发生错误: %v", err)) } if err := validate.RegisterValidation("payMethod", validatePayMethod); err != nil { panic(fmt.Sprintf("注册 payMethod 验证器时发生错误: %v", err)) } } // 弱口令列表 var weakPasswords = []string{ "12345678", "password", "123456789", "qwerty", "123456", "letmein", "1234567", "welcome", "abc123", "password1", "1234", "111111", "admin", } // Validate 校验参数逻辑 func Validate(req interface{}) error { if err := validate.Struct(req); err != nil { // 检查 err 是否是 ValidationErrors 类型 if validationErrors, ok := err.(validator.ValidationErrors); ok { for _, validationErr := range validationErrors { field := validationErr.StructField() tag := validationErr.Tag() return errors.New(GetErrorMessage(field, tag)) } } else { // 其他错误处理 return fmt.Errorf("验证时出现未知错误: %v", err) } } return nil } // 自定义的名称验证 func validName(fl validator.FieldLevel) bool { name := fl.Field().String() validNamePattern := `^[\p{Han}]+$` matched, _ := regexp.MatchString(validNamePattern, name) return matched } // 自定义的手机号验证 func validmobile(fl validator.FieldLevel) bool { phone := fl.Field().String() validmobilePattern := `^1[3-9]\d{9}$` matched, _ := regexp.MatchString(validmobilePattern, phone) return matched } // 自定义正则表达式校验 yyyyMMdd 格式 func validDate(fl validator.FieldLevel) bool { date := fl.Field().String() validDatePattern := `^\d{4}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$` matched, _ := regexp.MatchString(validDatePattern, date) return matched } // 自定义身份证校验(增强版) // 校验规则: // 1. 格式:18位,前6位地区码(首位不为0),7-14位出生日期,15-17位顺序码,18位校验码 // 2. 出生日期必须合法(验证年月日有效性,包括闰年) // 3. 校验码按照GB 11643-1999标准计算验证 func validIDCard(fl validator.FieldLevel) bool { idCard := fl.Field().String() // 1. 基本格式验证:地区码(6位) + 年(4位) + 月(2位) + 日(2位) + 顺序码(3位) + 校验码(1位) validIDPattern := `^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[\dXx]$` matched, _ := regexp.MatchString(validIDPattern, idCard) if !matched { return false } // 2. 验证出生日期的合法性 year, _ := strconv.Atoi(idCard[6:10]) month, _ := strconv.Atoi(idCard[10:12]) day, _ := strconv.Atoi(idCard[12:14]) // 构造日期并验证是否合法(time包会自动处理闰年等情况) birthDate := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC) if birthDate.Year() != year || int(birthDate.Month()) != month || birthDate.Day() != day { return false // 日期不合法,如2月30日、4月31日等 } // 3. 验证校验码(按照GB 11643-1999标准) return validateIDCardChecksum(idCard) } // 验证身份证校验码(GB 11643-1999标准) func validateIDCardChecksum(idCard string) bool { // 加权因子 weights := []int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2} // 校验码对应值 checksumChars := []byte{'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'} sum := 0 for i := 0; i < 17; i++ { num := int(idCard[i] - '0') sum += num * weights[i] } // 计算校验码 checksum := checksumChars[sum%11] lastChar := idCard[17] // 支持小写x if lastChar == 'x' { lastChar = 'X' } return byte(lastChar) == checksum } func validBankCard(fl validator.FieldLevel) bool { bankCard := fl.Field().String() // 银行卡号一般是13到19位的数字 validBankCardPattern := `^\d{13,19}$` matched, _ := regexp.MatchString(validBankCardPattern, bankCard) return matched } func validUSCI(fl validator.FieldLevel) bool { usci := fl.Field().String() // 社会信用代码为18位数字和大写字母的组合,最后一位为校验码 validUSCIPattern := `^[1-9A-Z]{2}[0-9]{6}[0-9A-Z]{9}[0-9A-Z]$` matched, _ := regexp.MatchString(validUSCIPattern, usci) return matched } // 自定义的手机号类型验证(可以为空) func validMobileType(fl validator.FieldLevel) bool { mobileType := fl.Field().String() if mobileType == "" { return true // 如果为空,认为是有效的 } // 校验是否是 CTCC, CMCC, CUCC 之一 validTypes := map[string]bool{ "CTCC": true, // 中国电信 "CMCC": true, // 中国移动 "CUCC": true, // 中国联通 } return validTypes[mobileType] } // 自定义密码强度校验函数 func validatePassword(fl validator.FieldLevel) bool { password := fl.Field().String() // 检查密码是否在弱口令列表中 for _, weakPwd := range weakPasswords { if strings.ToLower(password) == weakPwd { return false } } return true } // 支付方式 func validatePayMethod(fl validator.FieldLevel) bool { payMethod := fl.Field().String() if payMethod == "" { return true // 如果为空,认为是有效的 } validTypes := map[string]bool{ "alipay": true, // 中国电信 "wechatpay": true, // 中国移动 } return validTypes[payMethod] }