【问题标题】:Check string for 1 number, 1 letter and be between 5-15 characters in length检查字符串是否包含 1 个数字、1 个字母且长度在 5-15 个字符之间
【发布时间】:2017-05-13 23:36:40
【问题描述】:

我正在使用以下扩展来确保一个字符串至少有 1 个数字、1 个字母和 5-15 个字符的长度,我觉得它可以更有效。有什么建议吗?

func checkPassword(password : String) -> Bool{

    if password.characters.count > 15 || password.characters.count < 5 {
        return false
    }


    let capitalLetterRegEx  = ".*[A-Za-z]+.*"
    let texttest = NSPredicate(format:"SELF MATCHES %@", capitalLetterRegEx)
    let capitalresult = texttest.evaluate(with: password)

    let numberRegEx  = ".*[0-9]+.*"
    let texttest1 = NSPredicate(format:"SELF MATCHES %@", numberRegEx)
    let numberresult = texttest1.evaluate(with: password)

    let specialRegEx  = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ0123456789"
    let texttest2 = NSPredicate(format:"SELF MATCHES %@", specialRegEx)
    let specialresult = !texttest2.evaluate(with: password)




    if !capitalresult || !numberresult || !specialresult  {
        return false
    }

    return true

}

【问题讨论】:

    标签: regex swift validation passwords predicate


    【解决方案1】:

    使用正则表达式

    正则表达式是一种方法,但如果使用它,我们可能会将您的规范组合到一个正则表达式搜索中,利用以下问答中的积极前瞻断言技术:

    在这里,使用正则表达式:

    ^(?=.*[A-Za-z])(?=.*[0-9])(?!.*[^A-Za-z0-9]).{5,15}$
    
    // where:
    // (?=.*[A-Za-z])     Ensures string has at least one letter.
    // (?=.*[0-9])        Ensures string has at least one digit.
    // (?!.*[^A-Za-z0-9]) Ensures string has no invalid (non-letter/-digit) chars.
    // .{5,15}            Ensures length of string is in span 5...15.
    

    我还包括一个否定的前瞻断言 (?!...),以在给定任何无效字符的情况下使密码无效。

    我们可以如下实现正则表达式搜索:

    extension String {
        func isValidPassword() -> Bool {
            let regexInclude = try! NSRegularExpression(pattern: "^(?=.*[A-Za-z])(?=.*[0-9])(?!.*[^A-Za-z0-9]).{5,15}$")
            return regexInclude.firstMatch(in: self, options: [], range: NSRange(location: 0, length: characters.count)) != nil
        }
    }
    
    let pw1 = "hs1bés2"  // invalid character
    let pw2 = "12345678" // no letters
    let pw3 = "shrt"     // short
    let pw4 = "A12345"   // ok
    
    print(pw1.isValidPassword()) // false
    print(pw2.isValidPassword()) // false
    print(pw3.isValidPassword()) // false
    print(pw4.isValidPassword()) // true
    

    使用Set / CharacterSet

    一种 Swift 原生方法是使用明确指定的 Character 的集合:

    extension String {
        private static var numbersSet = Set("1234567890".characters)
        private static var alphabetSet = Set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ".characters)
    
        func isValidPassword() -> Bool {
            return 5...15 ~= characters.count &&
                characters.contains(where: String.numbersSet.contains) &&
                characters.contains(where: String.alphabetSet.contains)
        }
    }
    

    或者,类似地,使用Foundation 方法rangeOfCharacter(from:) 而不是CharacterSet 的:

    extension String {
        private static var numbersSet = CharacterSet(charactersIn: "1234567890")
        private static var alphabetSet = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ")
    
        func isValidPassword() -> Bool {
            return 5...15 ~= characters.count &&
                rangeOfCharacter(from: String.numbersSet) != nil &&
                rangeOfCharacter(from: String.alphabetSet) != nil
        }
    }
    

    如果您还想拒绝在指定集合中包含任何 字符的密码,您可以在集合的(反转)并集上添加搜索操作(可能您也允许您希望在此联合中包含一些特殊字符)。例如,对于 CharacterSet 示例:

    extension String {
        private static var numbersSet = CharacterSet(charactersIn: "1234567890")
        private static var alphabetSet = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ")
    
        func isValidPassword() -> Bool {
            return 5...15 ~= characters.count &&
                rangeOfCharacter(from: String.numbersSet.union(String.alphabetSet).inverted) == nil &&
                rangeOfCharacter(from: String.numbersSet) != nil &&
                rangeOfCharacter(from: String.alphabetSet) != nil
        }
    }
    
    let pw1 = "hs1bés2"  // invalid character
    let pw2 = "12345678" // no letter
    let pw3 = "shrt"     // too short
    let pw4 = "A12345"   // OK
    
    print(pw1.isValidPassword()) // false
    print(pw2.isValidPassword()) // false
    print(pw3.isValidPassword()) // false
    print(pw4.isValidPassword()) // true
    

    使用模式匹配

    只是为了讨论它,另一种方法是使用原生 Swift 模式匹配:

    extension String {
        private static var numberPattern = Character("0")..."9"
        private static var alphabetPattern = Character("a")..."z"
    
        func isValidPassword() -> Bool {
            return 5...15 ~= characters.count &&
                characters.contains { String.numberPattern ~= $0 } &&
                lowercased().characters.contains { String.alphabetPattern ~= $0 }
        }
    }
    
    let pw1 = "hs1bs2"
    let pw2 = "12345678"
    let pw3 = "shrt"
    let pw4 = "A12345"
    
    print(pw1.isValidPassword()) // true
    print(pw2.isValidPassword()) // false
    print(pw3.isValidPassword()) // false
    print(pw4.isValidPassword()) // true
    

    请注意,这种方法将允许带有变音符号(和类似)的字母作为最小 1 个字母规范通过,例如:

    let diacritic: Character = "é"
    print(Character("a")..."z" ~= diacritic) // true
    
    let pw5 = "12345é6"
    print(pw5.isValidPassword()) // true
    

    因为这些都包含在Character 范围"a"..."z";参见例如以下线程中的出色答案:

    【讨论】:

      【解决方案2】:

      感谢您的回复。我用它们来创建这个:

      extension String {
          private static var numbersSet = Set("1234567890".characters)
          private static var alphabetSet = Set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ".characters)
      
          func isValidPassword() -> Bool {
              let characterset = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ0123456789")
      
              return 5...15 ~= characters.count &&
                  characters.contains(where: String.numbersSet.contains) &&
                  characters.contains(where: String.alphabetSet.contains) &&
                  self.rangeOfCharacter(from: characterset.inverted) != nil
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-17
        • 2012-05-08
        • 1970-01-01
        • 2012-03-17
        相关资源
        最近更新 更多