iOS: как сохранить имя пользователя / пароль в приложении?

У меня есть экран входа в моем приложении iOS. Имя пользователя и пароль будут сохранены в NSUserDefaults и снова загрузиться в экран входа в систему при повторном входе в приложение (конечно, NSUserDefaults постоянны).

Теперь у пользователя есть возможность отключить функцию сохранения имени пользователя / пароля.

Итак NSUserDefaults будет очищен тогда.

Но в моем приложении мне нужно это имя пользователя / пароль для запросов к базе данных для пользователя. Итак: где хранить данные кроме NSUserDefaults? (Это место можно / нужно удалить, когда пользователь выйдет из приложения или выйдет из системы).

15 ответов

Решение

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

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

Включите Security.framework (в Xcode 3 щелкните правой кнопкой мыши папку фреймворков и добавьте существующий каркас. В Xcode 4 выберите свой проект, затем выберите цель, перейдите на вкладку "Фазы сборки" и нажмите "+" в разделе "Связать двоичные файлы с файлами") и KeychainItemWrapper .h & .m файлов в ваш проект, # импортируйте файл.h везде, где вам нужно использовать цепочку для ключей, а затем создайте экземпляр этого класса:

KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];

(YourAppLogin может быть любым, что вы выбрали для вызова элемента Keychain, и вы можете иметь несколько элементов при необходимости)

Затем вы можете установить имя пользователя и пароль, используя:

[keychainItem setObject:@"password you are saving" forKey:kSecValueData];
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];

Получить их с помощью:

NSString *password = [keychainItem objectForKey:kSecValueData];
NSString *username = [keychainItem objectForKey:kSecAttrAccount];

Или удалите их, используя:

[keychainItem resetKeychainItem];

Если вам нужна версия оболочки для ARC, перейдите по ссылке https://gist.github.com/1170641

Очень простое решение с помощью связки ключей.

Это простая обёртка для системы Keychain. Просто добавьте SSKeychain.h, SSKeychain.m, SSKeychainQuery.h а также SSKeychainQuery.m файлы в ваш проект и добавьте Security.framework к вашей цели.

Чтобы сохранить пароль:

[SSKeychain setPassword:@"AnyPassword" forService:@"AnyService" account:@"AnyUser"]

Чтобы восстановить пароль:

NSString *password = [SSKeychain passwordForService:@"AnyService" account:@"AnyUser"];

куда setPassword какое значение вы хотите сохранить и forService это переменная, под которой вы хотите сохранить, и учетная запись для какого пользователя / объекта пароль и любая другая информация.

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

Смотрите мой подробный ответ.

Я решил ответить, как использовать связку ключей в iOS 8, используя Obj-C и ARC.

1) Я использовал keychainItemWrapper (версия ARCifief) из GIST: https://gist.github.com/dhoerl/1170641/download- добавьте (+ скопируйте) KeychainItemWrapper.h и.m в ваш проект

2) Добавьте каркас безопасности в ваш проект (проверьте в проекте> Фазы сборки> Связать бинарный файл с библиотеками).

3) Добавьте библиотеку безопасности (#import) и KeychainItemWrapper (#import "KeychainItemWrapper.h") в файлы.h и.m, где вы хотите использовать цепочку ключей.

4) Чтобы сохранить данные в связку ключей:

NSString *emailAddress = self.txtEmail.text;
NSString *password = self.txtPasword.text;
//because keychain saves password as NSData object
NSData *pwdData = [password dataUsingEncoding:NSUTF8StringEncoding];

//Save item
self.keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
[self.keychainItem setObject:emailAddress forKey:(__bridge id)(kSecAttrAccount)];
[self.keychainItem setObject:pwdData forKey:(__bridge id)(kSecValueData)];

5) Считать данные (возможно, экран входа в систему при загрузке> viewDidLoad):

self.keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];

self.txtEmail.text = [self.keychainItem objectForKey:(__bridge id)(kSecAttrAccount)];

//because label uses NSString and password is NSData object, conversion necessary
NSData *pwdData = [self.keychainItem objectForKey:(__bridge id)(kSecValueData)];
NSString *password = [[NSString alloc] initWithData:pwdData encoding:NSUTF8StringEncoding];
self.txtPassword.text = password;

Наслаждайтесь!

Если у вас возникли проблемы с получением пароля с помощью оболочки ключей, используйте этот код:

NSData *pass =[keychain objectForKey:(__bridge id)(kSecValueData)];
NSString *passworddecoded = [[NSString alloc] initWithData:pass
                                           encoding:NSUTF8StringEncoding];

Зацените этот пример кода, я сначала попробовал обертку яблока из примера кода, но для меня это намного проще

Я смотрел на использование KeychainItemWrapper (версия ARC), но я не нашел его обертку Objective C настолько полезной, насколько хотелось.

Я использовал это решение от Kishikawa Katsumi, что означало, что я написал меньше кода и мне не пришлось использовать приведения для хранения значений NSString.

Два примера хранения:

[UICKeyChainStore setString:@"kishikawakatsumi" forKey:@"username"];
[UICKeyChainStore setString:@"P455_w0rd$1$G$Z$" forKey:@"password"];

Два примера получения

UICKeyChainStore *store = [UICKeyChainStore keyChainStore];
    // or
UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:@"YOUR_SERVICE"];

NSString *username = [store stringForKey:@"username"];
NSString *password = [store stringForKey:@"password"];

Попробуй это:

 KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
[keychainItem setObject:@"password you are saving" forKey:kSecValueData]; 
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];

может это поможет.

В приведенном выше коде есть небольшая ошибка (кстати, Дэйв, это было очень полезно, ваш пост, спасибо)

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

[self.keychainItem setObject:@"myCredentials" forKey:(__bridge id)(kSecAttrService)];

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

Чтобы обновить этот вопрос:

Для тех, кто использует Swift Checkout, эта реализация быстрого перетаскивания от Mihai Costea поддерживает группы доступа:

https://github.com/macostea/KeychainItemWrapper.swift/blob/master/KeychainItemWrapper.swift

Перед использованием цепочки для ключей: дважды подумайте, прежде чем хранить пароли. Во многих случаях может быть достаточно сохранения токена аутентификации (такого как идентификатор сеанса постоянства) и электронной почты или имени учетной записи. Вы можете легко аннулировать токены аутентификации, чтобы заблокировать несанкционированный доступ, требуя от пользователя повторной регистрации на скомпрометированном устройстве, но не требуя сброса пароля и повторной регистрации на всех устройствах (мы не только используем Apple, не так ли?).

Но теперь вы можете использовать NURLCredential вместо оболочки для ключей. Он делает то, что нам нужно сделать.

Для Swift вы можете использовать эту библиотеку:

https://github.com/jrendel/SwiftKeychainWrapper

Поддерживаются все версии swift.

Если у вашего приложения есть связанный домен, лучше использовать управление общими учетными данными . Это обеспечит лучший опыт для пользователя, и им управляет сама система.

Шаг 1:

Настройте свои связанные домены с помощью ключа веб-учетных данных

Шаг 2

Отметьте свои текстовые поля

      userIdTextField.textContentType = .username
passwordTextField.textContentType = .password

Шаг 3

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

      SecAddSharedWebCredential("www.example.com" as CFString, "user_id" as CFString, "password" as CFString) { error in
    if error != nil {
      // Handle error
      return
    }

    // The credentials have been successfully saved.
}

Теперь вы готовы к работе. Читать дальше ... ?!

Следующее должно работать просто отлично:

KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
[keychainItem setObject:@"password you are saving" forKey:kSecValueData]; 
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];
Другие вопросы по тегам