我正在尝试使用regexp编写密码验证功能,但不知道该怎么做.Golang正则表达式与其他语言不同.有人知道,这个正则表达式模式应该如何?
该模式应验证:
/*
* Password rules:
* at least 7 letters
* at least 1 number
* at least 1 upper case
* at least 1 special character
*/
Run Code Online (Sandbox Code Playgroud)
One*_*One 17
这实际上是不可能的,因为Go的正则表达式不支持回溯.
但是,它很容易实现,一个简单的例子:
func verifyPassword(s string) (sevenOrMore, number, upper, special bool) {
letters := 0
for _, c := range s {
switch {
case unicode.IsNumber(c):
number = true
case unicode.IsUpper(c):
upper = true
letters++
case unicode.IsPunct(c) || unicode.IsSymbol(c):
special = true
case unicode.IsLetter(c) || c == ' ':
letters++
default:
//return false, false, false, false
}
}
sevenOrMore = letters >= 7
return
}
Run Code Online (Sandbox Code Playgroud)
正确的正则表达式是......这里没有正则表达式.
您可以定义一个验证密码的自定义函数,并将其与其他框架结合使用,以帮助验证字段,例如mccoyst/validate(在本讨论中提到有关参数验证)
你还有go-validator/validator,它允许定义类似的验证(但我仍然会使用自定义验证器而不是一个或几个正则表达式).
注意:go regexp基于re2,一个高效的,有原则的正则表达式库).
因此,主要的权衡是没有反向引用,例如:
(abc)\1并没有匹配的后视.
作为交换,你得到高速正则表达式.
从相邻的答案中构建,我也编写了一个对我来说效果很好的辅助函数。这只是假设总体密码长度是令人满意的。看看以下...
func isValid(s string) bool {
var (
hasMinLen = false
hasUpper = false
hasLower = false
hasNumber = false
hasSpecial = false
)
if len(s) >= 7 {
hasMinLen = true
}
for _, char := range s {
switch {
case unicode.IsUpper(char):
hasUpper = true
case unicode.IsLower(char):
hasLower = true
case unicode.IsNumber(char):
hasNumber = true
case unicode.IsPunct(char) || unicode.IsSymbol(char):
hasSpecial = true
}
}
return hasMinLen && hasUpper && hasLower && hasNumber && hasSpecial
}
Run Code Online (Sandbox Code Playgroud)
isValid("pass") // false
isValid("password") // false
isValid("Password") // false
isValid("P@ssword") // false
isValid("P@ssw0rd") // true
Run Code Online (Sandbox Code Playgroud)
基于@OneOfOne的回答并改进了一些错误消息
package main
import (
"fmt"
"strings"
"unicode"
)
func verifyPassword(password string) error {
var uppercasePresent bool
var lowercasePresent bool
var numberPresent bool
var specialCharPresent bool
const minPassLength = 8
const maxPassLength = 64
var passLen int
var errorString string
for _, ch := range password {
switch {
case unicode.IsNumber(ch):
numberPresent = true
passLen++
case unicode.IsUpper(ch):
uppercasePresent = true
passLen++
case unicode.IsLower(ch):
lowercasePresent = true
passLen++
case unicode.IsPunct(ch) || unicode.IsSymbol(ch):
specialCharPresent = true
passLen++
case ch == ' ':
passLen++
}
}
appendError := func(err string) {
if len(strings.TrimSpace(errorString)) != 0 {
errorString += ", " + err
} else {
errorString = err
}
}
if !lowercasePresent {
appendError("lowercase letter missing")
}
if !uppercasePresent {
appendError("uppercase letter missing")
}
if !numberPresent {
appendError("atleast one numeric character required")
}
if !specialCharPresent {
appendError("special character missing")
}
if !(minPassLength <= passLen && passLen <= maxPassLength) {
appendError(fmt.Sprintf("password length must be between %d to %d characters long", minPassLength, maxPassLength))
}
if len(errorString) != 0 {
return fmt.Errorf(errorString)
}
return nil
}
// Let's test it
func main() {
password := "Apple"
err := verifyPassword(password)
fmt.Println(password, " ", err)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3861 次 |
| 最近记录: |