iOS: Як зберігати ім’я користувача / пароль у програмі?


276

У моєму додатку для iOS є екран входу. Ім’я користувача та пароль будуть збережені у програмі NSUserDefaultsта знову завантажуватимуться на екран входу, коли ви знову входите в додаток (звичайно, NSUserDefaultsє постійними).

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

Тож NSUserDefaultsбуде зачищено тоді.

Але в моєму додатку мені потрібно це ім’я користувача / пароль для запитів до бази даних для користувача. Отже: Де зберігати дані, крім NSUserDefaults? (Це місце можна / слід видалити, коли користувач вийшов із програми або вийшов).


Користувач може очистити його лише шляхом скидання пристрою або видалення програми. Я щось пропускаю?

3
І до речі, якщо дані потрібно видалити, коли користувач запускає додаток, чому б просто не зберегти його в оперативній пам’яті?

10
Вам слід серйозно розглянути можливість використання Keychain для зберігання імен користувачів та паролів замість NSUserDefaults.
Філіп Раделіч

1
Ви можете отримати основну ідею щодо впровадження swift3 тут
Anish Parajuli 웃

Чи потрібно завжди використовувати kSecValueData та kSecValueData як ключі? Або я можу використовувати будь-який рядок як ключ?
Ne AS

Відповіді:


424

Ви завжди повинні використовувати брелок для зберігання імен користувачів та паролів, а оскільки він зберігається надійно і доступний лише вашій програмі, видаляти його не потрібно, коли програма закриває (якщо це викликало ваше занепокоєння).

Apple надає зразок коду, який зберігає, читає та видаляє елементи брелоків, і ось як використовувати клас обгортки брелоків із цього зразка, що значно спрощує використання Keychain.

Включіть Security.framework (у Xcode 3 клацніть правою кнопкою миші папку фреймворків та додайте існуючий фреймворк. У Xcode 4 виберіть проект, потім виберіть ціль, перейдіть на вкладку Фази збірки та натисніть + під посиланням Бінарне з'єднання з файлами) та KeychainItemWrapper .h &. м файлів у ваш проект, # імпортуйте .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];

5
Я оновив свою відповідь кодом та описом. Це не так важко, як ви думали.
Філіп Раделіч

44
УВАГА! Додайте до своєї відповіді, що лише "копіювати KeychainItemWrapper" недостатньо! У мене була проблема, що я не можу згодом її створити! Ви повинні додати проект безпеки.framework до свого проекту, що KeychainItemWrapper буде працювати! (HowTo: Select Project -> Select Target -> Select Tab "Build Phases" -> Select "Link Binary With Libaries" -> "+" -> add Security.Framework)
Kovu

63
Використовуючи ARC, компілятор буде кричати на вас за використання констант kSecValueDataі kSecAttrAccountв коді Objective-C, тому обов'язково додайте їх, використовуючи (__bridge id), наприклад, [keychainItem setObject:obj forKey:(__bridge id)kSecValueData];
Джо Ханкін

7
KeychainItemWrapper.m, здається, має витік пам'яті у рядку 196. Змінення рядка на "self.keychainItemData = [[[[NSMutableDictionary alloc] init] autorelease]]". виправляє це.
Олоф

12
Під час використання ARC тут було надано оновлений код . Подивіться на Лістинг 2-1. Хоча підхід той самий.
Рік


48

Дуже просте рішення за допомогою брелоків .

Це проста обгортка для системного брелока. Просто додайте 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в яку змінну, яку ви хочете зберегти, і обліковий запис для того, для якого користувача / об’єкта використовується пароль та будь-яка інша інформація.


Чи знаєте ви, як використовувати sskeychain для синхронізації програм з тим же ім'ям користувача та паролем?
Джо Шамурак

4
як ви зберігаєте ім'я користувача, крім пароля? Як видалити весь обліковий запис із SSKeychain? Обидва документи не згадуються
користувач798719

2
Щоб отримати ім’я користувача, зробіть NSString *username = [[SSKeychain accountsForService:@"AnyService"][0] valueForKey:@"acct"]. Це має спрацювати нормально, якщо ви використовуєте лише один обліковий запис. Як завжди, не забудьте перевірити довжину масиву, перш ніж намагатись отримати доступ до індексу 0.
Джаред Ціна

27

Ви можете просто використовувати NSURLCredential, це збереже як ім’я користувача, так і пароль у брелоку всього за два рядки коду .

Дивіться мою детальну відповідь .


13

Я вирішив відповісти, як використовувати брелок в 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

Якщо у вас виникли проблеми із завантаженням пароля за допомогою обгортки брелоків, використовуйте цей код:

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

3

оформити цей зразок коду я спробував спочатку обгортку яблука з зразкового коду, але це для мене набагато простіше


2

спробуйте це:

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

нехай це допоможе.


2

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

Я використовував це рішення по Kishikawa Кацого , що означало , що я написав менше коди і не повинен використовувати зліпки для зберігання значень 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"];

2

У наведеному вище коді є невелика помилка (до речі, Дейв був дуже корисним вашим повідомленням дякую)

У тій частині, де ми зберігаємо облікові дані, для правильної роботи йому також потрібен наступний код.

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

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


2

Щоб оновити це питання:

Для тих, хто використовує Swift Checkout, ця швидка реалізація перетягування та підтримка групи Mihai Costea, що підтримує групи доступу:

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

Перш ніж використовувати брелок, подумайте двічі перед збереженням паролів. У багатьох випадках зберігання маркера аутентифікації (наприклад, ідентифікатор сеансу збереження) та електронної пошти чи імені облікового запису може бути достатньо. Ви можете легко визнати недійсними маркери аутентифікації, щоб заблокувати несанкціонований доступ, вимагаючи від користувача повторного входу на компрометований пристрій, але не вимагаючи скидання пароля та повторного входу на всіх пристроях (ми використовуємо не лише Apple, чи не так?).


1

Але тепер ви можете перейти на NURLCredional замість обгортки брелоків. Це робить те, що нам потрібно зробити.



0

Наступне має працювати добре:

KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
[keychainItem setObject:@"password you are saving" forKey:kSecValueData]; 
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.