iOS: как сохранить имя пользователя / пароль в приложении? - PullRequest
271 голосов
/ 07 августа 2011

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

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

Таким образом, NSUserDefaults будет очищено.

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

Ответы [ 14 ]

420 голосов
/ 07 августа 2011

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

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

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

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

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

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

[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];
97 голосов
/ 24 марта 2012

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

48 голосов
/ 30 ноября 2012

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

Это простая оболочка для системы 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 - это то, под какой переменной вы хотите сохранить, и для какого пользователя / объекта указывается пароль и любая другая информация.

27 голосов
/ 02 августа 2013

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

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

13 голосов
/ 12 июня 2015

Я решил ответить, как использовать связку ключей в 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;

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

11 голосов
/ 28 февраля 2014

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

NSData *pass =[keychain objectForKey:(__bridge id)(kSecValueData)];
NSString *passworddecoded = [[NSString alloc] initWithData:pass
                                           encoding:NSUTF8StringEncoding];
3 голосов
/ 07 августа 2011

оформить заказ образец кода Сначала я попробовал обертку Apple из примера кода, но для меня это намного проще

2 голосов
/ 24 июня 2016

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

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

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

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

2 голосов
/ 30 июня 2015

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

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

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

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

2 голосов
/ 30 января 2014

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

Я использовал это решение от Кишикава Кацуми , что означало, что я написал меньше кода и мне не пришлось использовать приведения для хранения значений 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"];
...