TouchID для аутентификации системного пароля

Я хочу использовать TouchID для аутентификации моего собственного приложения.

1. Я хочу, чтобы пользователь мог нажать "Ввести код доступа", чтобы вызывать экран с кодом доступа к системе, чтобы пройти аутентификацию, если успех затем входит в мое собственное приложение.
Но я не знаю, как это сделать, чтобы передать код проверки подлинности с паролем, например, следующий экран в случае 'LAErrorUserFallback' enter image description here

Вот мой код:

LAContext *context = [[LAContext alloc] init];
__block  NSString *msg;
__block  BOOL bAuth;
// show the authentication UI with our reason string
[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:NSLocalizedString(@"Unlock APP With FingerPrint", nil) reply:
^(BOOL success, NSError *authenticationError) {

   if (success) {
      bAuth = YES;
      msg =[NSString stringWithFormat:NSLocalizedString(@"EVALUATE_POLICY_SUCCESS", nil)];
      dispatch_async(dispatch_get_main_queue(), ^{
         [[MYAppDelegate theDelegate] initializeAppAfterKeyVaultUnlocked];
      });
      NSLog(@"%@",msg);
   } else {
      bAuth = NO;
      switch (authenticationError.code) {
         case LAErrorAuthenticationFailed:
            msg = [NSString stringWithFormat:NSLocalizedString(@"Authentication Failed", nil)];
            // ...
            break;

         case LAErrorUserCancel:
            msg = [NSString stringWithFormat:NSLocalizedString(@"User pressed Cancel button", nil)];
            dispatch_async(dispatch_get_main_queue(), ^{
               [[MYAppDelegate theDelegate] exitAndLock];
            });

            break;

         case LAErrorUserFallback:
            msg = [NSString stringWithFormat:NSLocalizedString(@"User pressed \"Enter Password\"", nil)];
            //Here I want to fallback to iOS build-in passcode authenticate view, and get the auth result.
            break;

         default:
            msg = [NSString stringWithFormat:NSLocalizedString(@"Touch ID is not configured", nil)];
            // ...
            break;
      }
      NSLog(@"%@",authenticationError.localizedDescription);

   }


}];

Ответ 1

Теперь в iOS 9 это довольно просто: вам просто нужно использовать LAPolicyDeviceOwnerAuthentication вместо LAPolicyDeviceOwnerAuthenticationWithBiometrics

Итак, в вашем коде вы просто замените это:

[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:NSLocalizedString(@"Unlock APP With FingerPrint", nil) reply:
^(BOOL success, NSError *authenticationError) {

При этом:

[context evaluatePolicy:LAPolicyDeviceOwnerAuthentication localizedReason:NSLocalizedString(@"Unlock APP With FingerPrint", nil) reply:
^(BOOL success, NSError *authenticationError) {

Таким образом, когда пользователь не может выполнить аутентификацию с помощью отпечатка пальца, будет включен параметр "ввести пароль", который будет вызывать экран ввода кода системного пароля.

Ответ 2

В моем понимании вам нужно будет самостоятельно создать экран кода доступа, если вы хотите использовать функцию оценкиPolicy.

Если вы используете keychain, функция SecItemCopyMatching автоматически возвращается к коду доступа, если аппликатура терпит неудачу. Вот ссылка о том, как это сделать (см. Раздел 3): https://www.secsign.com/fingerprint-validation-as-an-alternative-to-passcodes/

Ответ 3

Не пробовал, но это сообщение требует, что вы можете использовать систему, следуя здесь (Это работает только с iOS 8 или новее).

Или (это то, что я сделал) вы можете создать свой экран ввода пароля (для поддержки более старых версий iOS), мой контроллер имеет представление ввода кода доступа, которое будет отображаться, когда пользователь выбирает использовать пароль. В этот момент вызов назад из метода оценкиPolicy вернется с помощью LAErrorUserFallback, который может быть временем для открытия вашего пользовательского экрана кода доступа.

что-то вроде этого:

-(void)maybeShowTouchIDMessage {
  if (![SettingsManager sharedManager].isUseTouchID || self.createPassCodeMode) {
    self.shieldView.hidden = YES;
    return;
  }

  self.shieldView.hidden = NO;
  self.shieldView.alpha = 1.0;

  LAContext *context = [[LAContext alloc] init];

  NSError *evalError = nil;
  if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&evalError] ) {
    __weak SecurityWindowViewController *weakSelf = self;
    [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
            localizedReason:@"Use touch id \n or hit \"Cancel\" to enter passcode"
                      reply:^(BOOL success, NSError *error) {
                        dispatch_async(dispatch_get_main_queue(), ^{
                          SecurityWindowViewController *strongSelf = weakSelf;
                          if (success) {
                            [strongSelf hideWithSuccess:YES];
                          } else if (error){
                            NSString *errorMessage;
                            BOOL showError = NO;
                            switch (error.code) {
                              case LAErrorAuthenticationFailed:
                                errorMessage = @"Sorry couldn't autheticate";
                                showError = YES;
                                break;
                              case LAErrorPasscodeNotSet:
                                errorMessage = @"Sorry couldn't autheticate";
                                showError = YES;
                                break;
                              case LAErrorTouchIDNotEnrolled:
                                errorMessage = @"Touch ID has no enrolled fingers";
                                showError = YES;
                                break;
                              default:
                                showError = NO;
                                break;
                            }
                            [UIView animateWithDuration:0.5 animations:^{
                              strongSelf.shieldView.alpha = 0.0;
                            } completion:^(BOOL finished) {
                              strongSelf.shieldView.hidden = YES;
                            }];
                            if (showError) {
                              UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                                              message:errorMessage
                                                                             delegate:nil
                                                                    cancelButtonTitle:@"Ok"
                                                                    otherButtonTitles:nil];
                              [alert show];

                            }
                          }
                        });
                      }];

  } 

Ответ 4

Вы можете добавить еще один случай и вызвать экран своего пароля.

Вот мой код:

    LAContext *myContext = [[LAContext alloc] init];
    NSError *authError = nil;
    NSString *myLocalizedReasonString = strMessage;
    objFlockr.pVerificationBlock = objResponse;
    if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
        if (!isShow) {

            myContext.localizedFallbackTitle = @"";
        }
        else
        {
           myContext.localizedFallbackTitle =  @"Set Up Passcode";
        }

        [myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
                  localizedReason:myLocalizedReasonString
                            reply:^(BOOL succes, NSError *error) {

                                if  (!AppDel.firstAttampt && succes && !isShow)
                                {
                                    if (objFlockr.pVerificationBlock)
                                        objFlockr.pVerificationBlock(1);
                                }
                                else if (succes) {
                                    if (objFlockr.pVerificationBlock)
                                        objFlockr.pVerificationBlock(0);
                                    NSLog(@"User authenticated");
                                } else {

                                    switch (error.code) {
                                        case LAErrorAuthenticationFailed:
                                            NSLog(@"Authentication Failed");
                                            if (objFlockr.pVerificationBlock)
                                                objFlockr.pVerificationBlock(1);

                                            break;

                                        case LAErrorUserCancel:
                                            NSLog(@"User pressed Cancel button");
                                            if (objFlockr.pVerificationBlock)
                                                objFlockr.pVerificationBlock(3);
                                            break;

                                        case LAErrorUserFallback:
                                            NSLog(@"User pressed \"Enter Password\"");
                                            if (objFlockr.pVerificationBlock)
                                                objFlockr.pVerificationBlock(4);
                                            break;

                                        default:
                                            [self showMessage:@"Touch ID is not configured" withTitle:@"Error"];
                                            if (objFlockr.pVerificationBlock)
                                                objFlockr.pVerificationBlock(2);
                                            NSLog(@"Touch ID is not configured");
                                            break;
                                    }

                                    NSLog(@"Authentication Fails");
                                }
                            }];
    } else {
        NSLog(@"Can not evaluate Touch ID");
        [self showMessage:@"Can not evaluate TouchID" withTitle:@"Error"];
    }