2012-05-10 8 views
69

Actualmente estoy almacenando el nombre de usuario (correo electrónico) y un hash salado del correo electrónico y la contraseña en iOS KeyChain. Estoy usando la versión ARC'ified que se encuentra here.iOS KeyChain no recuperar los valores del fondo

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

Todo esto funciona bien cuando tengo que tirar de la señal de salida para mis llamadas de red mientras la aplicación está activa. Funciona para iniciar sesión desde un inicio limpio, así como todas las llamadas de red en todo momento. El problema comienza cuando la aplicación está en segundo plano.

Tenga en cuenta que esto solo ocurre esporádicamente y todavía no he definido el contenido de una versión o dispositivo de iOS específico.

El usuario dispara una ubicación (monitoreo de región) y quiero actualizar el servidor con su estado. Intento sacar la ficha del llavero, de la misma manera que hago para cada otra llamada de red, y actualizo el estado. Pero para algunos usuarios, el valor es nulo. Sin eso, no puedo actualizar las cosas de la red. ¿Por qué funcionaría esto para la mayoría, pero no para un pequeño porcentaje?

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

he vuelto a la versión no-ARC del keychainwrapper, pero aún así obtener los mismos resultados. Agradecería cualquier comentario sobre esto. Es solo una pequeña parte de mis usuarios, pero es un problema que me gustaría solucionar y no preocuparme. Gracias por adelantado.

Además, todos mis antecedentes se configuran en un backgroundTask para evitar que se agote el tiempo de espera. No estoy teniendo ningún problema con el trabajo que rodea al llavero, pero no dejo que las cosas avancen hasta que mi token esté lleno.

EDIT He descubierto mi problema con el llavero al no recuperar los valores del fondo. Publicaré la respuesta a continuación y la aceptaré, ya que creo que esta pregunta puede ser valiosa para otros más adelante.

Respuesta

93

Mi pregunta estaba cerca de la marca por el motivo, pero no del todo. Después de leer blog tras blog, tutorial tras tutorial, finalmente encontré uno que daba una pista de lo que podría estar sucediendo.

Pantallas de inicio bloqueadas. Los tutoriales de llavero siempre dejaron la configuración de accesibilidad para el llavero en blanco, por lo que el valor predeterminado sería el nivel de acceso más bajo/más seguro de Apple. Sin embargo, este nivel no permite el acceso al llavero si el usuario tiene un código de acceso en la pantalla de bloqueo. ¡Bingo! Esto explica el comportamiento esporádico y por qué esto solo le sucede a un pequeño porcentaje de usuarios.

Una línea de código, resuelve todo el desastre.

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

Agregue esta línea donde estoy estableciendo los valores de nombre de usuario y contraseña. Funciona de maravilla. Espero que esto ayude a alguien por ahí. Me confundió por un buen tiempo hasta que pude juntar las piezas.

+1

Gracias! Esto fue muy útil. –

+0

Me alegro de poder ayudar. Me desconcertó por mucho tiempo. –

+1

¡Muchas gracias por compartir esto! – pxlshpr

43

Use kSecAttrAccessibleAfterFirstUnlock en lugar de kSecAttrAccessibleAlways.


De Apple's documentation:

kSecAttrAccessibleAfterFirstUnlock
The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user.

After the first unlock, the data remains accessible until the next restart. This is recommended for items that need to be accessed by background applications. Items with this attribute migrate to a new device when using encrypted backups.

+3

Esta respuesta debería ser un comentario ... – Frizlab

0

En mi caso, watchOS2 accede a los datos llavero en el lado IOS.

Al principio, kSecAttrAccessibleWhenUnlockedThisDeviceOnly se utiliza. Puedo leer los datos sin importar si el iPhone está bloqueado o no. Es muy confuso para mí que voy a recibir un error cuando el reloj está tratando de acceder al llavero: : SecTrustEvaluate [hoja IssuerCommonName SubjectCommonName]

Y algún caso se convertirá en: : error SecOSStatusWith: [- 25308] dominio de error = NSOSStatusErrorDomain Code = -25308 "ks_crypt: e00002e2 no pudo 'oe' elemento (clase 6, bolsa: 0) Acceso al elemento intentado mientras llavero está bloqueado." UserInfo = {NSDescription = ks_crypt: e00002e2 no pudo 'oe' elemento (clase 6, bolsa: 0) Acceso al elemento intentado mientras llavero está bloqueado.}

Actualizaré mi respuesta si consigo más información.

Cuestiones relacionadas