Go语言validator密码验证问题:正则报错且oneof无法添加特殊字符
解决go-playground/validator/v10密码验证问题
问题分析
oneof标签误用:oneof是用来匹配枚举固定值的(比如oneof=admin user guest),完全不适合用来检查密码是否包含不同类型的字符,所以你第一个验证规则根本不生效。- 正则表达式错误:你写的正则
^(?=.*[a-zA-Z0-9!@#$%^&.?/]).$有两处关键问题:- 末尾的
.仅匹配单个字符,应该改为.*才能匹配任意长度的密码; - 正则没有分别校验大写、小写、数字、特殊字符四个条件,只是检查包含其中一类,不符合需求;
- 正则语法错误导致validator解析失败,抛出"undefined"错误。
- 末尾的
正确解决方案
方案一:自定义验证函数(推荐,可读性更高)
自定义一个验证函数,明确检查四个要求:
package main import ( "fmt" "unicode" "github.com/go-playground/validator/v10" ) // 自定义密码验证逻辑 func validatePassword(fl validator.FieldLevel) bool { password := fl.Field().String() var ( hasUpper bool hasLower bool hasNumber bool hasSpecial bool ) // 定义允许的特殊字符集合 specialChars := map[rune]bool{ '@': true, '#': true, '$': true, '%': true, '^': true, '&': true, '.': true, '?': true, } for _, char := range password { switch { case unicode.IsUpper(char): hasUpper = true case unicode.IsLower(char): hasLower = true case unicode.IsNumber(char): hasNumber = true case specialChars[char]: hasSpecial = true } } // 必须同时满足四个条件 return hasUpper && hasLower && hasNumber && hasSpecial } type UserReg struct { Username string `validate:"required,min=4,max=15"` Email string `validate:"required,email"` Password string `validate:"required,min=8,max=20,eqfield=ConfirmPassword,password"` ConfirmPassword string `validate:"required,min=8,max=20"` } func main() { validate := validator.New() // 注册自定义验证器 if err := validate.RegisterValidation("password", validatePassword); err != nil { fmt.Println("注册验证器失败:", err) return } ut := UserReg{ Username: "Joe23", Email: "Joe@joe.com", Password: "Pa$$w0rd", ConfirmPassword: "Pa$$w0rd", } err := validate.Struct(ut) fmt.Println(err) // 验证通过时输出 <nil> }
方案二:修正正则表达式
使用正确的正向预查正则,注意用反引号包裹结构体标签避免转义问题:
type UserReg2 struct { Username string `validate:"required,min=4,max=15"` Email string `validate:"required,email"` Password string `validate:"required,min=8,max=20,eqfield=ConfirmPassword,regexp=^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[@#$%^&.?]).+$"` ConfirmPassword string `validate:"required,min=8,max=20,regexp=^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[@#$%^&.?]).+$"` }
正则规则说明:
(?=.*[A-Z]):确保包含至少一个大写字母(?=.*[a-z]):确保包含至少一个小写字母(?=.*[0-9]):确保包含至少一个数字(?=.*[@#$%^&.?]):确保包含至少一个指定的特殊字符.+$:匹配任意长度的有效字符(配合min/max标签控制密码长度)
内容的提问来源于stack exchange,提问作者Bob Rusch
相关产品推荐
相关产品推荐

