[iphone] iOS 키 체인이 백그라운드에서 값을 검색하지 않음

현재 iOS KeyChain에 사용자 이름 (이메일)과 이메일 및 비밀번호의 솔트 된 해시를 저장하고 있습니다. 여기에 있는 ARC 버전을 사용하고 있습니다 .

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];

앱이 활성화되어있는 동안 네트워크 호출을 위해 토큰을 꺼내야 할 때이 모든 것이 잘 작동합니다. 깨끗한 시작에서 로그인하는 것은 물론 전체 네트워크 호출에 대해 작동합니다. 앱이 백그라운드에있을 때 문제가 시작됩니다.

이것은 산발적으로 만 발생하며 특정 iOS 버전 또는 기기에 아직 고정하지 않았습니다.

사용자가 위치를 이동하고 (지역 모니터링) 서버에 상태를 업데이트하고 싶습니다. 다른 모든 네트워크 호출에 대해 수행하는 것과 동일한 방식으로 키 체인에서 토큰을 꺼내고 상태를 업데이트하려고합니다. 그러나 일부 사용자의 경우 값이 nil입니다. 그것 없이는 네트워크 항목을 업데이트 할 수 없습니다. 왜 이것이 대부분의 경우 효과가 있지만 적은 비율에는 효과가 없습니까?

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

ARC 버전의 keychainwrapper로 돌아 갔지만 여전히 동일한 결과를 얻습니다. 이에 대한 의견을 보내 주시면 감사하겠습니다. 내 사용자의 작은 부분에 불과하지만 내가 고치고 싶은 문제이며 걱정하지 마십시오. 미리 감사드립니다.

또한 모든 백그라운드 작업은 시간 초과를 방지하기 위해 backgroundTask에 설정됩니다. 키 체인을 둘러싼 작업에 문제가 없지만 토큰이 채워질 때까지 일을 진행하지 않습니다.

편집
나는 배경에서 값을 검색하지 않는 키 체인 문제를 알아 냈습니다. 아래 답변을 게시하고 나중에이 질문이 다른 사람들에게 가치가있을 수 있다고 생각하므로 수락하겠습니다.



답변

내 질문은 그 이유 때문에 표시에 가깝지만 정답은 아닙니다. 블로그, 튜토리얼, 튜토리얼을 읽은 후 마침내 무슨 일이 일어날 지에 대한 힌트를주는 것을 발견했습니다.

잠긴 홈 화면. 키 체인 튜토리얼은 항상 키 체인에 대한 접근성 설정을 비워 두었으므로 기본적으로 Apple의 가장 낮은 / 가장 안전한 액세스 수준으로 설정됩니다. 그러나이 수준에서는 사용자가 잠금 화면에 암호가있는 경우 키 체인 접근을 허용하지 않습니다. 빙고! 이것은 산발적 인 행동과 이것이 소수의 사용자에게만 발생하는 이유를 설명합니다.

한 줄의 코드로 전체 문제를 해결합니다.

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

사용자 이름과 암호 값을 설정하는 곳에이 줄을 추가합니다. 매력처럼 작동합니다. 이것이 누군가를 도울 수 있기를 바랍니다. 조각들을 모을 수있을 때까지 꽤나 당혹 스러웠습니다.


답변

사용 kSecAttrAccessibleAfterFirstUnlock대신에 kSecAttrAccessibleAlways.

에서 애플의 설명서 :

kSecAttrAccessibleAfterFirstUnlock
키 체인 항목의 데이터는 사용자가 기기를 한 번 잠금 해제 할 때까지 다시 시작한 후 액세스 할 수 없습니다.

첫 번째 잠금 해제 후에는 다음에 다시 시작할 때까지 데이터에 액세스 할 수 있습니다. 백그라운드 애플리케이션에서 액세스해야하는 항목에 권장됩니다. 이 속성이있는 항목은 암호화 된 백업을 사용할 때 새 장치로 마이그레이션됩니다.


답변

제 경우에는 watchOS2가 iOS 측의 키 체인 데이터에 액세스합니다.

처음에는 kSecAttrAccessibleWhenUnlockedThisDeviceOnly가 사용됩니다. iPhone이 잠겨 있든 없든 데이터를 읽을 수 있습니다. 시계가 키 체인에 액세스하려고 할 때 오류가 발생한다는 점이 매우 혼란 스럽습니다. : SecTrustEvaluate [leaf IssuerCommonName SubjectCommonName]

그리고 어떤 경우에는 다음과 같이됩니다. : SecOSStatusWith error : [-25308] Error Domain = NSOSStatusErrorDomain Code = -25308 “ks_crypt : e00002e2가 ‘oe’항목에 실패했습니다 (class 6, bag : 0) 키 체인이 잠겨있는 동안 항목에 대한 액세스를 시도했습니다. ” UserInfo = {NSDescription = ks_crypt : e00002e2가 ‘oe’항목에 실패했습니다 (클래스 6, bag : 0) 키 체인이 잠겨있는 동안 시도한 항목에 대한 액세스.}

더 많은 정보를 얻으면 답변을 업데이트하겠습니다.


답변

이는 개발자의 관점에서 어느 정도 모호한 Apple의 데이터 보호 정책으로 인해 발생할 수 있습니다. 해결 방법은 앱이 시작될 때 키 체인에 액세스 할 수 있는지 확인하고, 액세스 할 수없는 경우 앱 유형에 따라 앱을 종료 할 수 있습니다 (적절한 팝업 사용).

+(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]);
}


답변