iOS KeyChain arka plandan değerleri almıyor


87

Şu anda kullanıcı adını (e-posta) ve e-posta ve şifrenin tuzlu bir karmasını iOS KeyChain'de saklıyorum. Burada bulunan ARC tarafından belirlenmiş sürümü kullanıyorum .

KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyCustomIdentifier" accessGroup:nil];
[wrapper setObject:APP_NAME forKey:(__bridge id)kSecAttrService];
[wrapper setObject:email forKey:(__bridge id)kSecAttrAccount];
[wrapper setObject:token forKey:(__bridge id)kSecValueData];

Bu, uygulama etkinken ağ aramalarım için belirteci çıkarmam gerektiğinde iyi çalışıyor. Temiz bir başlangıçtan ve tüm ağ çağrılarından oturum açmak için çalışır. Uygulama arka planda olduğunda sorun başlar.

Unutmayın, bu sadece ara sıra oluyor ve henüz belirli bir iOS sürümüne veya cihazına sabitlemedim.

Kullanıcı bir konumu gösteriyor (bölge izleme) ve sunucuyu durumuyla güncellemek istiyorum. Diğer ağ aramalarında yaptığım gibi jetonu anahtar zincirinden çıkarmaya ve durumu güncellemeye çalışıyorum. Ancak bazı kullanıcılar için değer sıfırdır. Onsuz, ağ öğelerini güncelleyemiyorum. Bu neden çoğu kişi için işe yarasın ama küçük bir yüzde için değil?

KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyCustomIdentifier" accessGroup:nil];
NSString *token = [wrapper objectForKey:(__bridge id)kSecValueData];

Keychainwrapper'ın ARC olmayan sürümüne geri döndüm, ancak yine de aynı sonuçları alıyorum. Bununla ilgili herhangi bir geri bildirim almaktan memnuniyet duyarım Bu, kullanıcılarımın yalnızca küçük bir kısmı, ancak bu, düzeltmek istediğim ve endişelenmek istemediğim bir sorun. Şimdiden teşekkürler.

Ayrıca, tüm arka plan çalışmalarım, işlerin zaman aşımına uğramasını önlemek için bir arka plan görevinde ayarlandı. Anahtar zincirini çevreleyen çalışmayla ilgili herhangi bir sorun yaşamıyorum, ancak simgem dolana kadar işlerin ilerlemesine izin vermiyorum.

DÜZENLE Anahtar zincirinin arka plandaki değerleri alamamasıyla ilgili sorunumu çözdüm. Cevabı aşağıda yayınlayacağım ve bu sorunun daha sonra başkaları için değerli olabileceğini düşündüğüm için kabul edeceğim.

Yanıtlar:


110

Sorum neden olduğu için işarete yakındı, ama tam olarak değil. Blogdan sonra blogdan sonra öğreticiyi okuduktan sonra, sonunda neler olabileceğine dair bir ipucu veren bir tane buldum.

Kilitli ana ekranlar. Anahtar zinciri eğitimleri, anahtar zinciri için erişilebilirlik ayarlarını her zaman boş bıraktı, bu nedenle varsayılan olarak Apple'ın en düşük / en güvenli erişim düzeyine ayarlandı. Ancak bu seviye, kullanıcının kilit ekranında bir şifresi varsa anahtar zinciri erişimine izin vermez. Bingo! Bu, düzensiz davranışı ve bunun neden yalnızca küçük bir kullanıcı yüzdesine olduğunu açıklar.

Bir satır kod, tüm karışıklığı çözer.

[wrapper setObject:(__bridge id)kSecAttrAccessibleAlways forKey:(__bridge id)kSecAttrAccessible];

Kullanıcı adı ve şifre değerlerini ayarladığım bu satırı ekleyin. Tıkır tıkır çalışıyor. Umarım bu oradaki birine yardımcı olur. Parçaları bir araya getirene kadar bir süre kafamı karıştırdı.


1
Teşekkürler! Bu çok yardımcı oldu.
Rich Waters

3
Haftalardır bununla tam anlamıyla uğraşıyoruz. Sen bir hayat kurtarıcısın!
OC Rickard

15
Lütfen …AccessibleAlwaysmümkünse kaçının veya yalnızca sınırlı ayrıcalıklar sağlayan bir jeton saklayın (örneğin, yeni yayın öğelerini okumanıza izin veren ancak göndermenize izin vermeyen bir jeton). Bunu yaparak açıkça bir şifreleme düzeyinden vazgeçmiş oluyorsunuz. Uygulamanız ilk kilit açma işlemine kadar bekleyebilirse, belki de en iyisi …AfterFirstUnlockkullanıcılarınızı kullanıp önce cihazlarının kilidini açmaya yönlendirmek olacaktır.
millenomi

14
Bu gerçekten kötü bir fikir çünkü bu kimlik bilgilerinin artık korunmadığı anlamına geliyor. Biraz daha çalışılırken, bir , sadece arka planda gerekli olmasını beklediğiniz sınırlı erişim için kullanılandan daha fazla türev kimlik bilgisi . Bu sınırlı kimlik bilgisi bir süre sonra sona erebilir ve uygulama her açıldığında yenisi oluşturulur ve eskileri geçersiz kılar. Bu, türev kimlik bilgilerinin tehlikeye girmesi durumunda kullanıcıyı güvende tutar. Bunu öğrenmek için WWDC 2013 oturumu 204'e bakın.
Joey Hagedorn

7
@ JoeyHagedorn'da yankılanıyor - 44:24 işaretinde WWDC 2013 Oturum 204 "Çoklu Görevde Yenilikler" ve 25:30 işaretinde WWDC 2013 Oturum 709 "Anahtar Zinciri ile Sırları Koruma" bölümünü dinleyin. Bu konuşmaların metin içeriğini asciiwwdc.com
Shazron

64

kSecAttrAccessibleAfterFirstUnlockBunun yerine kullanın kSecAttrAccessibleAlways.


Gönderen Apple'ın belgelerinde :

kSecAttrAccessibleAfterFirstUnlock
Cihazın kilidi kullanıcı tarafından bir kez açılıncaya kadar, anahtarlık öğesindeki verilere yeniden başlatmanın ardından erişilemez.

İlk kilit açmadan sonra, veriler bir sonraki yeniden başlatmaya kadar erişilebilir durumda kalır. Bu, arka plan uygulamalarıyla erişilmesi gereken öğeler için önerilir.Bu özelliğe sahip öğeler, şifreli yedeklemeler kullanılırken yeni bir cihaza taşınır.


4
Bu cevap bir yorum olmalı…
Frizlab

Bu cevap mükemmel görünüyor çünkü kSecAttrAccessibleAlwayszaten kullanımdan kaldırıldı
Sazzad Hissain Khan

1

Benim durumumda watchOS2, iOS tarafında anahtarlık verilerine erişiyor.

Başlangıçta kSecAttrAccessibleWhenUnlockedThisDeviceOnly kullanılır. İPhone kilitli olsun ya da olmasın verileri okuyabiliyorum. Watch anahtar zincirine erişmeye çalışırken hata alacağım çok kafa karıştırıcı:: SecTrustEvaluate [leaf IssuerCommonName SubjectCommonName]

Ve bazı durumlarda şöyle olacaktır:: SecOSStatusWith error: [- 25308] Error Domain = NSOSStatusErrorDomain Code = -25308 "ks_crypt: e00002e2 'oe' item (sınıf 6, bag: 0) anahtar zinciri kilitliyken denenen öğeye erişim. " UserInfo = {NSDescription = ks_crypt: e00002e2, 'oe' öğesini başaramadı (sınıf 6, çanta: 0) Anahtar zinciri kilitliyken denenen öğeye erişim.}

Daha fazla bilgi alırsam cevabımı güncelleyeceğim.


0

Bu, geliştiricilerin bakış açısından belli bir düzeyde belirsiz olan Apples veri koruma politikası nedeniyle olabilir. Çözüm, uygulamanın başlatıldığında anahtar zincirinin erişilebilir olup olmadığını kontrol etmesidir, erişilebilir değilse, uygulama türlerinize bağlı olarak uygulamanızı (uygun açılır pencereyle) öldürebilirsiniz.

+(BOOL) isKeychainAccessible
{
    NSString *keychainTestKey = @"keychainTestKey";
    NSString *keychainTestValue = @"keychainTestValue";
    [self createKeychainValue:keychainTestValue forIdentifier:keychainTestKey];
    NSString *loadedValue = [self keychainStringFromMatchingIdentifier:keychainTestKey];
    [self deleteItemFromKeychainWithIdentifier:keychainTestKey];
    return ([keychainTestValue isEqualToString: loadedValue]);
}
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.