使用regexp进行密码验证

zer*_*ing 5 regex go

我正在尝试使用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)


Von*_*onC 7

正确的正则表达式是......这里没有正则表达式.

您可以定义一个验证密码的自定义函数,并将其与其他框架结合使用,以帮助验证字段,例如mccoyst/validate(在本讨论中提到有关参数验证)

你还有go-validator/validator,它允许定义类似的验证(但我仍然会使用自定义验证器而不是一个或几个正则表达式).


注意:go regexp基于re2,一个高效的,有原则的正则表达式库).

因此,主要的权衡是没有反向引用,例如:(abc)\1没有匹配的后视.
作为交换,你得到高速正则表达式.


scn*_*iro 6

从相邻的答案中构建,我也编写了一个对我来说效果很好的辅助函数。这只是假设总体密码长度是令人满意的。看看以下...

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)


Pra*_*dey 5

基于@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)