iOS: Bir uygulamada kullanıcı adı / şifre nasıl saklanır?


276

İOS uygulamamda bir giriş ekranım var. Kullanıcı adı ve şifre uygulamaya kaydedilir NSUserDefaultsve tekrar uygulamaya girdiğinizde tekrar giriş ekranına yüklenir (tabii ki NSUserDefaultskalıcıdır).

Artık kullanıcı, kullanıcı adı / şifre kaydetme özelliğini devre dışı bırakma olanağına sahiptir.

Böylece o NSUserDefaultszaman temizlenecek.

Ama benim app kullanıcı için veritabanı sorguları için bu kullanıcı adı / şifre gerekir. Öyleyse: Dışındaki veriler nerede saklanır NSUserDefaults? (Kullanıcı uygulamadan veya oturumu kapattığında bu yer silinebilir / silinmelidir).


Kullanıcı yalnızca cihazı sıfırlayarak veya uygulamayı kaldırarak temizleyebilir. Bir şey mi kaçırıyorum?

3
Bu arada, kullanıcı uygulamadan çıktığında verilerin silinmesi gerekiyorsa, neden sadece RAM'de kalmıyorsunuz?

10
NSUserDefaults yerine kullanıcı adlarını ve parolaları saklamak için Keychain'i ciddiye almalısınız.
Filip Radelic

1
Hızlı3 uygulaması hakkında temel fikri buradan edinebilirsiniz
Anish Parajuli 웃

Lütfen anahtar olarak her zaman kSecValueData ve kSecValueData kullanmalıyım? Veya anahtar olarak herhangi bir dizeyi kullanabilir miyim?
Ne AS

Yanıtlar:


424

Kullanıcı adlarını ve şifreleri saklamak için her zaman Anahtarlık kullanmalısınız ve güvenli ve yalnızca uygulamanız tarafından erişilebilir olduğundan, uygulama sonlandırıldığında onu silmenize gerek yoktur (endişeniz bu ise).

Apple örnek kod sağlar anahtarlık öğelerini saklayan, okuyan ve silen ve işte bu örnekteki anahtarlık sarma sınıfını Keychain kullanarak büyük ölçüde basitleştiren nasıl kullanacağınız.

Security.framework'ı ekleyin (Xcode 3'te çerçeveler klasörünü sağ tıklatın ve mevcut çerçeveyi ekleyin. Xcode 4'te projenizi seçin, ardından hedefi seçin, Aşama Oluştur sekmesine gidin ve Dosyaları İkili Dosyalara Bağla altında + işaretini tıklayın) ve KeychainItemWrapper. H &. m dosyalarını projenize ekleyin, # anahtarlık kullanmanız gereken her yerde .h dosyasını içe aktarın ve ardından bu sınıfın bir örneğini oluşturun:

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

( AppLogin , Anahtarlık öğenizi çağırmayı seçtiğiniz bir şey olabilir ve gerekirse birden fazla öğeye sahip olabilirsiniz)

Ardından kullanıcı adını ve şifreyi kullanarak şunları yapabilirsiniz:

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

Bunları kullanarak alın:

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

Veya bunları kullanarak silin:

[keychainItem resetKeychainItem];

5
Cevabımı kod ve açıklama ile güncelledim. Düşündüğünüz kadar zor değil.
Filip Radelic

44
Attantion! Lütfen cevabınıza ekleyin, sadece "kopya KeychainItemWrapper" yeterli değildir! Daha sonra inşa edemediğim bir sorunum vardı! KeychainItemWrapper'ın çalışacağı projenize security.framework eklemeniz gerekir! (Nasıl Yapılır: Proje Seç -> Hedef Seç -> Sekme "Derleme Aşamaları" seç -> "İkili Belgelere Bağla" -> "+" -> Güvenlik Ekle. Çerçeve)
Kovu

63
ARC kullanırken, derleyici sabitleri kSecValueDatave kSecAttrAccountObjective-C kodunu kullandığınız için size bağırır , bu yüzden bunları kullanarak (__bridge id), örneğin [keychainItem setObject:obj forKey:(__bridge id)kSecValueData];
Joe Hankin 6:13

7
KeychainItemWrapper.m satır 196'da bellek sızıntısı var gibi görünüyor. Satırı "self.keychainItemData = [[[NSMutableDictionary tahsis] init] otomatik yayın];" düzeltir.
Olof

12
ARC kullanılırken güncellenen kod burada Apple tarafından verilmiştir . Liste 2-1'e bakınız. Her ne kadar yaklaşım aynı olsa da.
Rick


48

Anahtarlıklar ile çok kolay bir çözüm .

Keychain sistemi için basit bir sarıcı. Sadece eklemek SSKeychain.h, SSKeychain.m, SSKeychainQuery.hve SSKeychainQuery.mprojenize dosyaları ve hedefe Security.framework ekleyin.

Bir şifreyi kaydetmek için:

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

Bir şifre almak için:

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

Nerede setPasswordkaydetmiş ve istediğiniz değeri budur forServicebunu altında kaydedilir ve hesabı kullanıcı / parola nesne ve diğer bilgiler için ne için olduğunu istediklerini değişkendir.


Uygulamaları aynı kullanıcı adı ve şifreyle senkronize etmek için sskeychain'i nasıl kullanacağınızı biliyor musunuz?
Joe Shamuraq

4
şifreye ek olarak bir kullanıcı adını nasıl saklarsınız? Hesabın tamamını SSKeychain'den nasıl silebilirsiniz? Her ikisi de dokümanlar belirtilmez
user798719

2
Kullanıcı adı almak için yapın NSString *username = [[SSKeychain accountsForService:@"AnyService"][0] valueForKey:@"acct"]. Yalnızca bir hesap kullanıyorsanız, bu durumun iyi olması gerekir. Her zaman olduğu gibi, 0 dizinine erişmeye çalışmadan önce dizi uzunluğunu kontrol ettiğinizden emin olun.
Jared Price

27

Sadece kullanabilirsiniz NSURLCredential, hem kullanıcı adını hem de şifreyi anahtarlığa sadece iki kod satırında kaydeder .

Ayrıntılı cevabımı görün .


13

Obj-C ve ARC kullanarak iOS 8'de anahtarlığın nasıl kullanılacağına cevap vermeye karar verdim.

1) GIST'ten keychainItemWrapper'ı (ARCifief sürümü) kullandım: https://gist.github.com/dhoerl/1170641/download - KeychainItemWrapper.h ve .m'yi projenize ekleyin (+ kopyalayın)

2) Güvenlik çerçevesini projenize ekleyin (projeyi kontrol edin> Aşama oluşturma> İkili kitaplıkları bağlama)

3) Güvenlik kitaplığını (#import) ve KeychainItemWrapper (#import "KeychainItemWrapper.h") anahtarlığını kullanmak istediğiniz .h ve .m dosyasına ekleyin.

4) Verileri anahtarlığa kaydetmek için:

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) Verileri okuyun (muhtemelen yükleme sırasında giriş ekranı> 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;

Zevk almak!


11

Anahtarlık sarmalayıcısını kullanarak şifreyi alırken sorun yaşıyorsanız şu kodu kullanın:

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


2

bunu dene:

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

yardımcı olur.


2

KeychainItemWrapper (ARC sürümü) kullanmaya baktım ama Objective C paketleyicisini istediğiniz kadar sağlıklı bulamadım.

Ben kullanılan bu çözümü tarafından Kishikawa Katsumi ben az kod yazdım ve NSString değerleri depolamak için atmalarını kullanmak yoktu geliyordu.

İki depolama örneği:

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

Geri alma için iki örnek

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

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

2

Yukarıdaki kodda küçük bir hata var (bu arada Dave çok yararlı oldu yazı teşekkür ederim)

Kimlik bilgilerini kaydettiğimiz bölümde, düzgün çalışması için aşağıdaki koda da ihtiyacı vardır.

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

büyük olasılıkla, aynı kimlik bilgileriyle ikinci kez (tekrar) oturum açmaya çalıştığımızda, anahtarlık öğelerinde zaten atanmış olduklarını ve uygulamanın çöktüğünü görüyoruz. Yukarıdaki kod ile bir cazibe gibi çalışır.


2

Bu soruyu güncellemek için:

Swift kontrolünü kullananlar için, Mihai Costea'nın erişim gruplarını destekleyen bu sürükle ve bırak hızlı uygulaması:

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

Anahtarlık kullanmadan önce: şifreleri saklamadan önce iki kez düşünün. Çoğu durumda bir kimlik doğrulama belirteci (kalıcılık oturumu kimliği gibi) ve e-posta veya hesap adı depolamak yeterli olabilir. Yetkisiz erişimi engellemek için kimlik doğrulama jetonlarını kolayca geçersiz kılabilir, kullanıcının güvenliği ihlal edilmiş cihazda tekrar oturum açmasını gerektirir, ancak sıfırlama şifresi gerektirmez ve tüm cihazlarda tekrar oturum açmak zorunda kalmazsınız (yalnızca Apple kullanmıyoruz?).


1

Ancak, şimdi anahtarlık sarıcı yerine NURLCredential'a gidebilirsiniz. Yapmamız gerekeni yapıyor.



0

Aşağıdakiler iyi çalışmalıdır:

KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
[keychainItem setObject:@"password you are saving" forKey:kSecValueData]; 
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.