我使用ios鑰匙串(keychainItemWrapper
/SSKeychain
)來存儲我的應用程序的登錄令牌並保持登錄狀態。目前,我在包含我的令牌,令牌過期和刷新令牌的鑰匙串中存儲簡單的NSDictionary
。我將它序列化爲NSData並使用kSecValueData
進行存儲。我還設置了kSecAttrAccount
和kSecAttrService
,但不要將這些用於身份驗證。ios在KeyChain中存儲登錄令牌無法檢索,很少和隨機,但始終如一
這個工程的時候很大,約95%。問題在於,隨機地,不可預知地和偶爾地,當我請求它檢索令牌時,鑰匙串不返回數據。通常在離開應用程序一段適中的時間後,重新打開它。它不一定是來自後臺,或者經過任何特定的延遲。
它在下面要求我的NSData
並返回<>
而不是<ABCD EFGH IJKL ....>
時特別失敗。我認爲這是零。因此,代碼認爲用戶沒有登錄並立即將其放在我的應用程序的註冊/登錄登錄頁面上,沒有註銷錯誤,令牌過期錯誤等。如果我最小化應用程序,然後重新打開,它幾乎總是得到正確的鑰匙串信息和用戶再次登錄。
的時候遇到這將創建一個令人困惑的經歷。這也意味着用戶無法保持這種真正的100%登錄狀態,偶爾會被隨機註銷。我一直無法預測它或調試它,並改變鑰匙串庫,如下所示,並沒有爲我解決它。它發生在我和幾個TestFlight用戶以及我們的產品應用程序當前。
任何建議如何維持的時間鑰匙扣完整性和加載100%?我們準備在令牌上實現NSUserDefaults備份存儲以用於這些情況,這是我真的不想要存儲身份驗證令牌的。
儲存:
// load keychain
KeychainItemWrapper *keychainItem = [KeychainItemWrapper keyChainWrapperForKeyID:kcIdentifier];
NSString *firstLaunch = [keychainItem objectForKey: (__bridge id)(kSecAttrAccount)];
if (firstLaunch == nil){
// initialize if needed
[keychainItem setObject:email forKey: (__bridge id)(kSecAttrAccount)];
[keychainItem setObject:kcIdentifier forKey: (__bridge id)kSecAttrService];
[keychainItem setObject:(id)kSecAttrAccessibleAfterFirstUnlock forKey:(id)kSecAttrAccessible];
}
// serialize "auth" NSDictionary into NSData and store
NSString *error;
NSData *dictionaryData = [NSPropertyListSerialization dataFromPropertyList:auth format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
[keychainItem setObject:dictionaryData forKey:(id)kSecValueData];
加載:
// after similar KeychainItemWrapper initialization as above
NSData *dictionaryData = [keychainItem objectForKey:(id)kSecValueData];
NSString *error;
NSDictionary *auth = [NSPropertyListSerialization propertyListFromData:dictionaryData mutabilityOption:NSPropertyListImmutable format:nil errorDescription:&error];
NSString *token = auth[@"access_token"];
我也使用SSKeychain
庫CocoaPod就是廣泛使用,和周圍的鑰匙鏈邏輯的包裝嘗試。這是一個更清潔的訪問,但沒有同樣的問題。在這裏,我只是存儲NSString
值,因爲沒有直接的方式將NSData
存儲在lib中。
// store in keychain
[SSKeychain setAccessibilityType:kSecAttrAccessibleAfterFirstUnlock];
[SSKeychain setPassword:auth[@"access_token"] forService:SSKEYCHAIN_SERVICE account:SSKEYCHAIN_TOKEN];
[SSKeychain setPassword:auth[@"expires_at"] forService:SSKEYCHAIN_SERVICE account:SSKEYCHAIN_EXPIRES_AT];
[SSKeychain setPassword:auth[@"refresh_token"] forService:SSKEYCHAIN_SERVICE account:SSKEYCHAIN_REFRESH_TOKEN];
// load from keychain
[SSKeychain setAccessibilityType:kSecAttrAccessibleAfterFirstUnlock];
NSString *token = [SSKeychain passwordForService:SSKEYCHAIN_SERVICE account:SSKEYCHAIN_TOKEN];
NSString *expires_at = [SSKeychain passwordForService:SSKEYCHAIN_SERVICE account:SSKEYCHAIN_EXPIRES_AT];
NSString *refresh_token = [SSKeychain passwordForService:SSKEYCHAIN_SERVICE account:SSKEYCHAIN_REFRESH_TOKEN];
如果鑰匙串失敗,您應該得到一個錯誤代碼。它是什麼? – Segev
我有同樣的問題,其中檢索隨機失敗。這裏有一個輔助方法 - 鑰匙串錯誤代碼字符串:https://gist.github.com/inorganik/f9971e65f71e037650b39b5f182e157e – inorganik
我會嘗試記錄錯誤。它可能發生在我使用的庫內部,它不暴露&錯誤參數。 – Miro