Check Password String Strength Criteria in Swift

Check password string strength criteria in Swift

update: Xcode 8.3.2 • Swift 3.1

enum PasswordError: String, Error {
case eightCharacters
case oneUppercase
case oneLowercase
case oneDecimalDigit
}

extension String {
func validatePassword() throws {
guard count > 7
else { throw PasswordError.eightCharacters }
guard rangeOfCharacter(from: .uppercaseLetters) != nil
else { throw PasswordError.oneUppercase }
guard rangeOfCharacter(from: .lowercaseLetters) != nil
else { throw PasswordError.oneLowercase }
guard rangeOfCharacter(from: .decimalDigits) != nil
else { throw PasswordError.oneDecimalDigit }
}
}

let myPass = "12345678"

do {
try myPass.validatePassword()
print("valid password action")
} catch let error as PasswordError {
print("Password error:", error)
switch error {
case .eightCharacters:
print("Needs At Least Eight Characters action")
case .oneUppercase:
print("Needs At Least one Uppercase action")
case .oneLowercase:
print("Needs At Least one Lowercase action")
case .oneDecimalDigit:
print("Needs At Least One DecimalDigit action")
}
} catch {
print("error:", error)
}

How to implement a regex for password validation in Swift?

The regex is

(?:(?:(?=.*?[0-9])(?=.*?[-!@#$%&*ˆ+=_])|(?:(?=.*?[0-9])|(?=.*?[A-Z])|(?=.*?[-!@#$%&*ˆ+=_])))|(?=.*?[a-z])(?=.*?[0-9])(?=.*?[-!@#$%&*ˆ+=_]))[A-Za-z0-9-!@#$%&*ˆ+=_]{6,15}

Use RegEx to validate a password on iOS Swift

The main issue is that NSPredicate with MATCHES requires the full string to match and consume the whole input. Lookarounds - you are using lookaheads - do not consume text, that is, the texts they match are not added to the match value and the regex index stays where it was before attempting to match a lookaround pattern.

The last two parts can be thus fixed this way:

func isPasswordHasNumberAndCharacter(password: String) -> Bool {
let passRegEx = "(?=[^a-z]*[a-z])[^0-9]*[0-9].*"
let passwordTest = NSPredicate(format: "SELF MATCHES %@", passRegEx)
return passwordTest.evaluate(with: password)
}

func isPasswordHasNumberAndCharacterSign(password: String) -> Bool {
let passWordRegEx = "[a-zA-Z0-9!@#$%^&*]+"
let passwordTest = NSPredicate(format: "SELF MATCHES %@", passWordRegEx)
return passwordTest.evaluate(with: password)
}

The first part is OK, though you do not need the ^ and $ anchors (as the whole string input must match the pattern). However, to check a string length you do not even need a regex: see Get the length of a String.

Note:

  • ^(?=[^a-z]*[a-z])[^0-9]*[0-9].*\z matches a string that contains at least one lowercase ASCII letter and at least one ASCII digit
  • ^[a-zA-Z0-9!@#$%^&*]+$ will match a string that only contains ASCII letters, digits and some specific symbols. If you inlude a - make sure it is at the end. Escape both [ and ] if you need to add them, too.

If you want to combine all that into 1 regex you could use

let passRegEx = "(?=[^a-z]*[a-z])(?=[^0-9]*[0-9])[a-zA-Z0-9!@#$%^&*]{8,}"

Or, if you are not using the regex with the NSPredicate MATCHES, with anchors:

let passRegEx = "\\A(?=[^a-z]*[a-z])(?=[^0-9]*[0-9])[a-zA-Z0-9!@#$%^&*]{8,}\\z"

Password validation in UITextField in iOS

This is how I would do it. The validation should be done at the end when the user has typed in the password and not in between.I will not be using NSRegularExpression.

-(void)textFieldDidEndEditing:(UITextField *)textField{
int numberofCharacters = 0;
BOOL lowerCaseLetter,upperCaseLetter,digit,specialCharacter = 0;
if([textField.text length] >= 10)
{
for (int i = 0; i < [textfield.text length]; i++)
{
unichar c = [textfield.text characterAtIndex:i];
if(!lowerCaseLetter)
{
lowerCaseLetter = [[NSCharacterSet lowercaseLetterCharacterSet] characterIsMember:c];
}
if(!upperCaseLetter)
{
upperCaseLetter = [[NSCharacterSet uppercaseLetterCharacterSet] characterIsMember:c];
}
if(!digit)
{
digit = [[NSCharacterSet decimalDigitCharacterSet] characterIsMember:c];
}
if(!specialCharacter)
{
specialCharacter = [[NSCharacterSet symbolCharacterSet] characterIsMember:c];
}
}

if(specialCharacter && digit && lowerCaseLetter && upperCaseLetter)
{
//do what u want
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
message:@"Please Ensure that you have at least one lower case letter, one upper case letter, one digit and one special character"
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
}

}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
message:@"Please Enter at least 10 password"
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
}
}

Hope this helps...

Regex to validate password strength

You can do these checks using positive look ahead assertions:

^(?=.*[A-Z].*[A-Z])(?=.*[!@#$&*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{8}$

Rubular link

Explanation:

^                         Start anchor
(?=.*[A-Z].*[A-Z]) Ensure string has two uppercase letters.
(?=.*[!@#$&*]) Ensure string has one special case letter.
(?=.*[0-9].*[0-9]) Ensure string has two digits.
(?=.*[a-z].*[a-z].*[a-z]) Ensure string has three lowercase letters.
.{8} Ensure string is of length 8.
$ End anchor.

Swift live text field checking for characters from multiple arrays

It's easier if you use Set instead of Array. Here's an example:

private let upperCaseAll = Set("ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters)
private let lowerCaseAll = Set("abcdefghijklmnopqrstuvwxyz".characters)
private let numberAll = Set("0123456789".characters)
private let specialCharAll = Set("-/:;()$&@\".,?!'[]{}#%^\\|~<>€£¥".characters)

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// Determines what the new value of the text field will be
let newText = range.length == 0 ? textField.text! + string : (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)

// Turn that string into a Set of Characters
let characters = Set(newText.characters)

let hasUpperCase = !characters.intersect(self.upperCaseAll).isEmpty
let hasLowerCase = !characters.intersect(self.lowerCaseAll).isEmpty
let hasNumber = !characters.intersect(self.numberAll).isEmpty
let hasSpecialChar = !characters.intersect(self.specialCharAll).isEmpty

// Now turn your 4 other views to green/red as needed
print("hasUpperCase = \(hasUpperCase), hasLowercase = \(hasLowerCase), hasNumber = \(hasNumber), hasSpecialChar = \(hasSpecialChar)")
...

return true
}

Swift 5 - Error with the password validation regex

(?=^.{7,}$)(?=^.*[A-Z].*$)(?=^.*\d.*$).*

Short Explanation

  • (?=^.{7,}$) At least 7 characters long
  • (?=^.*[A-Z].*$) At least one uppercase letter
  • (?=^.*\d.*$) At least one number
  • .* Match the string that contains all assertions

See the regex demo

Swift Example

let phonePattern = #"(?=^.{7,}$)(?=^.*[A-Z].*$)(?=^.*\d.*$).*"#

func isValid(password: String) -> Bool {
return password.range(
of: phonePattern,
options: .regularExpression
) != nil
}

print(isValid(password: "Pass1")) // false
print(isValid(password: "Pass23word")) // true
print(isValid(password: "23password")) // false
print(isValid(password: "Greatpass13")) // true


Related Topics



Leave a reply



Submit