【问题标题】:Password validation in UITextField in iOSiOS UITextField 中的密码验证
【发布时间】:2013-02-14 10:50:15
【问题描述】:

我的 iPhone 应用程序中有 1 个UITextfield 作为密码。

我想通过以下验证来验证此文本字段。

  • 必须至少为 10 个字符
  • 必须至少包含一个小写字母、一个大写字母、一个数字和一个特殊字符
  • 有效的特殊字符是-@#$%^&+=^.*(?=.{10,})(?=.*d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$

如何限制UITextField 满足上述要求?

【问题讨论】:

    标签: objective-c validation ios5 passwords uitextfield


    【解决方案1】:

    这就是我的做法。验证应该在用户输入密码时完成,而不是在两者之间。我不会使用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];
       }
    }
    

    希望这会有所帮助...

    【讨论】:

    • 谢谢!它对我来说太棒了。
    【解决方案2】:

    您也可以使用Regex 来执行此操作。以下是我为您提供的几个示例:

    // *** Validation for Password ***
    
        // "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$" --> (Minimum 8 characters at least 1 Alphabet and 1 Number)
        // "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[$@$!%*#?&])[A-Za-z\\d$@$!%*#?&]{8,16}$" --> (Minimum 8 and Maximum 16 characters at least 1 Alphabet, 1 Number and 1 Special Character)
        // "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,}$" --> (Minimum 8 characters at least 1 Uppercase Alphabet, 1 Lowercase Alphabet and 1 Number)
        // "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[$@$!%*?&])[A-Za-z\\d$@$!%*?&]{8,}" --> (Minimum 8 characters at least 1 Uppercase Alphabet, 1 Lowercase Alphabet, 1 Number and 1 Special Character)
        // "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[$@$!%*?&])[A-Za-z\\d$@$!%*?&]{8,10}" --> (Minimum 8 and Maximum 10 characters at least 1 Uppercase Alphabet, 1 Lowercase Alphabet, 1 Number and 1 Special Character)
    

    列表中的第四个就是你的情况,下面的代码 sn-p 显示了如何使用它:

    -(BOOL)isValidPassword:(NSString *)passwordString
    {
        NSString *stricterFilterString = @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[$@$!%*?&])[A-Za-z\\d$@$!%*?&]{10,}";
        NSPredicate *passwordTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", stricterFilterString];
        return [passwordTest evaluateWithObject:passwordString];
    }
    

    使用方法:

    if(![self isValidPassword:txtPassword.text]) {
        /* Show alert: "Password must be minimum 10 characters,
           at least 1 Uppercase Alphabet, 1 Lowercase Alphabet, 
           1 Number and 1 Special Character" */
    }
    else {
        // Password is valid
    }
    

    【讨论】:

      【解决方案3】:

      条件:密码至少应包含8个字符,1个大写字母和1个数字

      Swift 3 中的解决方案

      你可以这样写字符串扩展

      extension String {
          func isValidPassword() -> Bool {
              let regularExpression = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[$@$!%*?&])[A-Za-z\\d$@$!%*?&]{8,}"
              let passwordValidation = NSPredicate.init(format: "SELF MATCHES %@", regularExpression)
      
              return passwordValidation.evaluate(with: self)
          }
      }
      
      //Example 1
      
      var password = "@Abcdef011" //string from UITextField (Password)
      password.isValidPassword() // -> true
      
      //Example 2
      
      var password = "Abcdef011" //string from UITextField 
      password.isValidPassword() // -> false
      

      或者你可以这样写函数,

      func validate(password: String) -> Bool
      {
          let regularExpression = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[$@$!%*?&])[A-Za-z\\d$@$!%*?&]{8,}"
      
          let passwordValidation = NSPredicate.init(format: "SELF MATCHES %@", regularExpression)
      
          return passwordValidation.evaluate(with: password)
      }
      

      这会给你同样的结果。

      【讨论】:

        【解决方案4】:

        斯威夫特 3

        检查密码是否强?

        1. 长度大于等于8
        2. 小写
        3. 大写
        4. 十进制数字
        5. !@#$%^&*()_-+ 等特殊字符是可选的

          为什么我不用正则表达式?

          因为在常规中很难支持保留字符 表达式语法。


         func isValidated(_ password: String) -> Bool {
             var lowerCaseLetter: Bool = false
             var upperCaseLetter: Bool = false
             var digit: Bool = false
             var specialCharacter: Bool = false
        
             if password.characters.count  >= 8 {
                 for char in password.unicodeScalars {
                     if !lowerCaseLetter {
                         lowerCaseLetter = CharacterSet.lowercaseLetters.contains(char)
                     }
                     if !upperCaseLetter {
                         upperCaseLetter = CharacterSet.uppercaseLetters.contains(char)
                     }
                     if !digit {
                         digit = CharacterSet.decimalDigits.contains(char)
                     }
                     if !specialCharacter {
                         specialCharacter = CharacterSet.punctuationCharacters.contains(char)
                     }
                 }
                 if specialCharacter || (digit && lowerCaseLetter && upperCaseLetter) {
                     //do what u want
                     return true
                 }
                 else {
                     return false
                 }
             }
             return false
         }
         let isVaildPass:Bool = isValidated("Test**00+-")
         print(isVaildPass)
        

        【讨论】:

          【解决方案5】:

          您可以使用以下函数验证您的密码验证,只需传递一个密码字符串,这将返回您的 BOOL 值。

          -(BOOL) isPasswordValid:(NSString *)pwd {
          
              NSCharacterSet *upperCaseChars = [NSCharacterSet characterSetWithCharactersInString:@"ABCDEFGHIJKLKMNOPQRSTUVWXYZ"];
              NSCharacterSet *lowerCaseChars = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyz"];
          
              //NSCharacterSet *numbers = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
          
              if ( [pwd length]<6 || [pwd length]>20 )
                  return NO;  // too long or too short
              NSRange rang;
              rang = [pwd rangeOfCharacterFromSet:[NSCharacterSet letterCharacterSet]];
              if ( !rang.length )
                  return NO;  // no letter
              rang = [pwd rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]];
              if ( !rang.length )
                  return NO;  // no number;
              rang = [pwd rangeOfCharacterFromSet:upperCaseChars];
               if ( !rang.length )
                   return NO;  // no uppercase letter;
              rang = [pwd rangeOfCharacterFromSet:lowerCaseChars];
              if ( !rang.length )
                  return NO;  // no lowerCase Chars;
              return YES;
          }
          

          【讨论】:

            【解决方案6】:

            对我来说最好的方法是使用NSPredicate 和正则表达式。 这是您的情况的正则表达式:^(?=.{10,})(?=.*[0-9])(?=.*[a-zA-Z])([@#$%^&amp;=a-zA-Z0-9_-]+)$

            目标C代码:

            NSString *regex = @"^(?=.{10,})(?=.*[0-9])(?=.*[a-zA-Z])([@#$%^&=a-zA-Z0-9_-]+)$";
            
            NSPredicate *passwordTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
            
            BOOL isValid = [passwordTest evaluateWithObject:yourTextfield.text];
            

            【讨论】:

              【解决方案7】:

              使用正则表达式(NSRegularExpression 类有关于如何编写模式本身的文档),然后:

              - (BOOL)textField:(UITextField *)theTextField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
                  //delete
                  if (string.length == 0) {
                      return YES;
                  }
              
                  if (self.regEx) {
                      NSMutableString* check = [NSMutableString stringWithString:theTextField.text];
                      [check replaceCharactersInRange:range withString:string];
                      NSTextCheckingResult* match = [self.regEx firstMatchInString:check options:0 range:NSMakeRange(0, [check length])];
                      if (match.range.length != check.length) {
                          return NO;
                      }
                  }
              }
              

              警告:以这种方式限制输入确实会让用户感到困惑。你输入再输入,你输入的字符就不会出现!

              我可能会在测试字段旁边使用一个小红色 (!),但我总是允许输入本身!

              【讨论】:

              • "以这种方式限制输入确实让用户感到困惑。" -- 特别是在隐藏的密码字段中!
              【解决方案8】:

              我有这个优雅的表单解决方案(如注册),您需要进行大量验证

              我的自定义 UITextField 中有插座:

              @IBInspectable var regexpValidation: String? = nil
              

              在情节提要中,我可以通过属性检查器访问它并像这样放置正则表达式字符串(用于电子邮件):

              [a-z0-9!#$%&amp;'*+/=?^_{|}~-]+(?:.[a-z0-9!#$%&'*+/=?^_{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?

              然后在我的子类中我有这个计算变量:

              @IBInspectable var regexpValidation: 字符串? = nil // 可选,在 InterfaceBuilder 中设置

              var inputIsValid: Bool {
                  get {
                      if let expr = regexpValidation {
                         return (text.rangeOfString(expr, options: NSStringCompareOptions.RegularExpressionSearch, range: nil, locale: nil) != nil)
                      } else {
                          return true
                      }
              
                  }
              }
              

              可以这样使用:

                 override func resignFirstResponder() -> Bool {
                      if (inputIsValid) {
                          return super.resignFirstResponder()
                      }
                      else {
                          text = ""
                          return false
                      }
                  }
              

              【讨论】:

                【解决方案9】:

                您需要在UITextField这个委托方法中编写您的验证代码

                - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
                

                您可能希望在实施过程中参考的几个链接

                how to use regular expression in iOS sdk

                iOS TextField Validation

                【讨论】:

                  【解决方案10】:

                  使用NSTextFieldDelegate 协议的control:isValidObject: 方法,它允许您验证NSTextField 的值。假设您已正确配置所有界面构建器,您可能会执行以下操作:

                  @interface PreferencesController : NSWindowController <NSTextFieldDelegate> {
                      IBOutlet NSTextField *username, *password;
                  }
                  
                  @end
                  
                  @implementation PreferencesController
                  
                  - (BOOL)control:(NSControl *)control isValidObject:(id)object
                  {
                      if (control == password) {
                        // Perform validation and return YES or NO
                      }
                  
                      return YES;
                  }
                  
                  @end
                  

                  【讨论】:

                  • 这不是在输入后触发的吗?他想限制输入......如果它被称为无聊,这很酷:)
                  • 确实是在输入后触发的。我没有将问题阅读为在输入期间限制按键。我认为这会让用户感到非常困惑。
                  • 这很令人困惑 - 我是根据经验说的:我会在我的答案中添加这个
                  【解决方案11】:

                  使用 RXSWIFT 的 SWIFT 5,一种更好、更简洁、反应灵敏的方法。

                  验证密码功能是这样的,显然您可以根据需要添加任意数量的条件。

                   func validatePassword(password: String) -> (Bool, String) {
                    //Minimum 8 characters at least 1 Alphabet and 1 Number:
                  var tuple: (Bool, String) = (true, "")
                  var string = "Requires atleast"
                  
                  if(password.rangeOfCharacter(from: CharacterSet.letters) == nil){
                      string = "uppercase"
                      tuple = (false, string)
                  
                  }
                  if(password.rangeOfCharacter(from: CharacterSet.decimalDigits) == nil){
                      string += ", number"
                         tuple = (false, string)
                  
                     }
                  if(password.count < 8 ){
                      string += ", 8 chars"
                         tuple = (false, string)
                  
                     }
                  return tuple }
                  
                  
                   func isPasswordValid(in string: String) -> Observable<(Bool, String)> {
                      return Observable.create { observer -> Disposable in
                  
                          let tuple = self.validation.validatePasswordForSymbol(password: string)
                  
                          observer.onNext(tuple)
                  
                  
                          return Disposables.create()
                      }
                  }
                  

                  您可以根据您的架构在 viewModel 或 VC 中使用上述功能。 然后在您的 VC 中调用如下相同的函数。

                  passwordTextField.rx.text
                              .orEmpty //1
                              .filter { $0.count >= 1 } //2
                              .flatMap { self.isPasswordValid(in: $0) }
                              .subscribe(onNext: { result in
                                  print("Valid password", result)
                                  //update UI here 
                                  // result will be like (false, "Requires atleast, 8 chars, number")
                              }).disposed(by: disposeBag)
                  

                  【讨论】:

                    猜你喜欢
                    • 2014-02-12
                    • 2017-09-28
                    • 1970-01-01
                    • 2013-11-17
                    • 2013-10-22
                    • 1970-01-01
                    • 2013-12-26
                    • 2016-05-19
                    • 2020-11-23
                    相关资源
                    最近更新 更多