iosのキーチェーン(keychainItemWrapper
/SSKeychain
)を使用してアプリケーションのログイントークンを保存し、ログイン状態を維持しています。現在、私は自分のトークン、トークンの有効期限、リフレッシュトークンを含むキーチェーンに単純なNSDictionary
を格納しています。私はそれをNSDataにシリアル化し、kSecValueData
を使って格納します。 kSecAttrAccount
とkSecAttrService
も設定しますが、認証用には使用しないでください。KeyChainにログイントークンを格納しているiosがまれにランダムに取得できませんでしたが、一貫して
これは、約95%の時間がかかります。問題は、ランダムに、予期せず、散発的に、私がトークンを取得するように要求したときにキーチェーンがデータを返さないということです。それは通常、アプリケーションを中断した後、再オープンするときです。それは、バックグラウンドからでなくても、特定の遅延の後である必要はありません。
NSData
の質問に特に失敗し、<ABCD EFGH IJKL ....>
の代わりに<>
が返されます。私はそれがゼロだと思う。したがって、コードは、ログアウトエラー、トークンの期限切れエラーなどなく、ユーザーがログインしていないと思ってすぐにアプリケーションのサインアップ/ログインのランディングページにドロップします。もし私がアプリを最小限に抑えてから再び開くと、ほとんど常に正しいキーチェーンinfoと入力し、再度ログインします。
これは、遭遇したときに混乱を招くことがあります。また、ユーザーはこの真の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];
ロード:私も広く利用可能であるSSKeychain
ライブラリCocoaPod、およびキーチェーンロジックのラッパーを使用してみましたが
// 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"];
。よりクリーンなアクセスですが、同じ問題で失敗します。ここにはの値を格納しているだけなので、libにNSData
を格納する直接の方法がないためです。
// 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
エラーを記録しようとします。私が使用しているライブラリの中で、&errorparamを公開していない可能性があります。 – Miro