2009-09-08 12 views
7

Tengo una aplicación que se comunica con un servidor que usa autenticación HTTP Digest.Uso de Autenticación HTTP Digest en el iPhone

Me parece que la gestión de 'sesión' en el iPhone es bastante "caja negra" para nosotros los desarrolladores. ¿Es cierto que no podemos ver cómo el marco maneja/persiste las sesiones de http?

Si solo estoy siendo tenue aquí, ¿alguien se preocuparía de explicarme cómo manejar probablemente la autenticación HTTP Digest en el iPhone?

Mi carrera básica a través de es:

  • hacer una petición a una URL segura
  • Server envía un cliente 401
  • crea y persiste una credencial, y lo pasa de nuevo al servidor
  • el servidor verifica la credencial, completa la solicitud si se verifica, envía otra 401 si no es así.
  • hacer una solicitud posterior para asegurar url
  • peticiones al servidor de autorización de nuevo ........

Esto funciona para las solicitudes individuales, pero si hago peticiones adicionales, posteriores, la autorización de solicitudes de servidor de nuevo. El servidor ha persistido en una sesión para el usuario en particular, pero el iPhone no realiza una solicitud dentro de la misma sesión por algún motivo ... Por lo tanto, el servidor tiene que descartar el objeto de autenticación y crear uno nuevo cada vez que el cliente realiza una solicitud a una url segura.

Estoy seguro de que este no es el comportamiento correcto.

Si nos fijamos en cómo un navegador se comporta de esta situación:

  • El navegador solicita datos de URL seguro
  • servidor envía 401
  • navegador solicita el usuario para credencial, persiste, la envía al servidor
  • servidor verifica credencial, devuelve datos si se verifica, envía otro 401 si no es así.
  • las solicitudes subsiguientes realizadas a las URL seguras no se solicitan para las credenciales porque el navegador administra la sesión.

Estoy creando NSURLCredential y persistiéndolo dentro de NSURLCrendtialStorage. Luego, cuando la aplicación recibe el 'didReceiveAuthenticationChallenge', recupero la credencial del almacenamiento y la devuelvo, creando la credencial si no existe (en la primera solicitud).

Cualquier ayuda sería muy apreciada. Gracias.

Respuesta

3

Lo primero es olvidarse de las sesiones HTTP, ya que no interactúan con la autenticación implícita de inicios de sesión activos (hay una especie de capacidad de información de sesión, pero es diferente).

De hecho, una de las principales razones para usar Digest es no tener que usar sesiones solo para mantener un estado de inicio de sesión. Las sesiones son pesadas y duelen la escalabilidad.

No podría decir con certeza cuál es su problema, pero sé lo que comprobaría primero, que es el uso correcto de la creación obsoleta y correcta de nonces.

Los agentes de usuario solo pueden gestionar la autenticación sin necesidad de volver a consultar al usuario si se les solicita gestionar el mismo nonce, o en otro caso lo veré más tarde (más fácil explicarlo en este orden).

Si tiene el mismo nonce utilizado en cada solicitud, el usuario-agente continuará usándolo junto con el "ha1" del usuario/pase para solicitar recursos posteriores. Esto se hace de forma preventiva, por lo que el desafío nunca ocurre.

Por supuesto, usar el mismo nonce introduce un elemento de inseguridad, ya que los ataques de reproducción se vuelven triviales para cualquiera que pueda oler el tráfico. Nonces tendrá que cambiar de forma regular.

Por lo tanto, si recibe una solicitud de un usuario-agente con un encabezado de Autorización no válido, pero la razón es inválida es que el nonce es incorrecto (está utilizando uno caducado) en su desafío incluye "añejo = verdadero "(predeterminado a falso). Esto le informa al usuario-agente que su razón para rechazar es que el nonce está desactualizado (por supuesto, la otra información también puede estar equivocada, pero eso no importa ya que no va a dejar que se reproduzca de ninguna manera).

Al recibir un estado tan antiguo = verdadero, el usuario-agente sabrá que no está autorizado, pero en lugar de volver a consultar al usuario (o lanzar una excepción si es un componente sin UI) volverá a intentarlo con el nuevo nonce.

No puedo decir si algo de esto es lo que te está afectando, pero la forma en que los nonces y la obsolescencia son determinados y señalados es ciertamente lo primero que miraría.

+0

Jasarien, ¿tomo la señal de que esto te pone en el camino correcto? (por mi curiosidad, y tal vez el beneficio de que otra persona encuentre el mismo problema). –

1

He escrito una aplicación para iPhone con autenticación HTTP y experimenté lo que describes. (Mi aplicación usa autenticación básica en lugar de la autenticación resumida, pero eso no hace una gran diferencia aquí.)

La causa del problema está en el lado del iPhone. El servidor debe responder con 401 si el iPhone no envía las credenciales en el encabezado de solicitud HTTP. Y, de hecho, no es posible aunque una vez que la credencial se almacena en el almacenamiento de credenciales.

Este extraño comportamiento tuvo un efecto severo en la velocidad de la aplicación ya que cada solicitud causó dos viajes ida y vuelta al servidor en lugar de uno (el primero con estado 401, el segundo con 200).

He resuelto por la configuración manual de las credenciales en el encabezado de la solicitud HTTP:

NSString* credentials = [NSString stringWithFormat: @"%@:%@", usr, pwd]; 
const char* credentialsChars = [credentials cStringUsingEncoding: NSUTF8StringEncoding]; 
credentials = [CommunicationUtil stringBase64WithData: (const UInt8*) credentialsChars length: strlen(credentialsChars)]; 
NSString* authorizationHeader = [NSString stringWithFormat: @"Basic %@", credentials]; 

NSMutableURLRequest* request = 
    [[NSMutableURLRequest alloc] initWithURL: url 
     cachePolicy: NSURLRequestReloadIgnoringLocalCacheData 
     timeoutInterval: 15]; 

    [request setValue: authorizationHeader forHTTPHeaderField: @"Authorization"]; 

Ahora mi aplicación funciona muy bien y es muy sensible.

La solución se verá ligeramente diferente para la autenticación resumida. Pero entenderás la idea.

+1

La autenticación implícita se verá * muy * diferente. Si ASIHTTPRequest ya lo admite, lo usaría en lugar de copiar algo de criptografía. –

+1

De acuerdo con los documentos, ASIHTTPRequest sí, así que iría con la sugerencia de tc. Te ahorrará muchos dolores de cabeza por tener que codificar todo esto manualmente. –

+0

He estudiado los detalles de la autenticación resumida y tengo que estar de acuerdo: su implementación es bastante engorrosa. La computación de los hashes MD5 es la parte más fácil. Manejar todos los detalles en el encabezado HTTP es la parte difícil. Entonces, sí: probablemente sea mejor probar ASIHTTPRequest. – Codo

Cuestiones relacionadas