Swift Keychain не может получить сохраненный пароль из viewDidLoad для функции автоматического входа - PullRequest
0 голосов
/ 28 февраля 2019

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

Вот моя реализация входа в систему, где цепочка для ключей сохраняет имя пользователя и пароль:

    func loginUser(from url: URL, with username: String, and password: String, completionHandler: @escaping (DrivetimeUserProfile?, DrivetimeAPIError.LoginError?) -> Void) { 

        let request = makeLoginRequest(url: url, with: username, password: password)

        let task = session.dataTask(with: request) { (data, response, error) in

            guard let data = data else {
                completionHandler(nil, .EmptyData)
                return
            }

            do {
                let userProfile = try JSONDecoder().decode(DrivetimeUserProfile.self, from: data)
                completionHandler(userProfile, nil)
                self.accountName = username
                self.keychainItem = KeychainPasswordItem(service: KeychainConfiguration.serviceName, account: username, accessGroup: KeychainConfiguration.accessGroup)
                try self.keychainItem?.savePassword(password)

            } catch {
                completionHandler(nil, .CannotDecodeJson)
            }
        }
        task.resume()
    }
}

Затем в моем loginViewController, при нажатии loginButton вызывается loginUser примерно так:

@IBAction func onLoginButtonTapped(_ sender: Any) {

    let url = URL(string: BASE_URL)!

    if !isUsernameAndPasswordIsFilled() {
        let alert = makeAlertDialogue(with: "Incomplete Information", description: "Please make you enter both username and password")
        present(alert, animated: true, completion: nil)
        return
    }

    client.loginUser(from: url, with: userNameTextField.text!, and: passwordTextField.text!) { [weak self] (userProfile, error)  in

        self?.performUIUpdate {
            guard error == nil else {
                self?.handleLoginError(error: error)
                return
            }
            self?.userProfile = userProfile
            self?.performSegue(withIdentifier: "mainTabBarController", sender: nil)
        }
    }
}

Но, когда я пытаюсь получить доступ к сохраненному паролю, он получает nil.Я сделал некоторую отладку, и я уверен, что это сохраняет его в связке ключей.Я даже создаю отдельный проект, чтобы доказать себе, что пример кода от Apple действительно работает.Может ли быть так, что я сохраняю пароль из фонового потока, и у меня есть доступ к цепочке для ключей в основном потоке в моем loginViewController?

Спасибо!

Обновление

Вот код доступа к цепочке для ключей в loginViewController:

override func viewDidLoad() {
    super.viewDidLoad()
    navigationController?.navigationBar.prefersLargeTitles = true

    print(try! client.keychainItem?.readPassword())

}

1 Ответ

0 голосов
/ 28 февраля 2019

Я только что установил пример проекта по вашей ссылке и протестировал работу.Я предполагаю, что вы настроили класс KeychainPasswordItem правильно.В вашем коде я вижу имя пользователя, вы можете проверить имя пользователя, которое является правильным с вашим паролем или нет.

if let accountName = accountName {
   do {
       let passwordItem = KeychainPasswordItem(service:KeychainConfiguration.serviceName, account: accountName, accessGroup: KeychainConfiguration.accessGroup)  
       accountNameField.text = passwordItem.account
       passwordField.text = try passwordItem.readPassword()
   }
   catch {
       fatalError("Error reading password from keychain - \(error)")
   }
}
...