2009-11-20 14 views
36

Estoy intentando acceder a un sitio web seguro a través de UIWebView. Cuando accedo a él a través de safari, recibo un desafío de autenticación, pero lo mismo no aparece en mi UIWebView en la aplicación. ¿Cómo puedo hacer que aparezca?¿Cómo mostrar el desafío de autenticación en UIWebView?

Cualquier puntero, código de muestra o enlaces serán de gran ayuda. Muchas gracias.

Respuesta

35

En realidad es superfácil ... Estoy seguro de que puede mostrar un UIAlertView cuando se muestra el delegado de desafío de autenticación (o antes de cargar la URL, si está seguro de que la URL que está buscando indicará para la información de inicio de sesión de autenticación). De todos modos, el truco es crear tu propio NSURLConnection y hago algo de lógica para guardar si se ha usado el delegado de autenticación.

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; 
{ 
    NSLog(@"Did start loading: %@ auth:%d", [[request URL] absoluteString], _authed); 

    if (!_authed) { 
     _authed = NO; 
     /* pretty sure i'm leaking here, leave me alone... i just happen to leak sometimes */ 
     [[NSURLConnection alloc] initWithRequest:request delegate:self]; 
     return NO; 
    } 

    return YES; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge; 
{ 
    NSLog(@"got auth challange"); 

    if ([challenge previousFailureCount] == 0) { 
     _authed = YES; 
     /* SET YOUR credentials, i'm just hard coding them in, tweak as necessary */ 
     [[challenge sender] useCredential:[NSURLCredential credentialWithUser:@"username" password:@"password" persistence:NSURLCredentialPersistencePermanent] forAuthenticationChallenge:challenge]; 
    } else { 
     [[challenge sender] cancelAuthenticationChallenge:challenge]; 
    } 
} 

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response; 
{ 
    NSLog(@"received response via nsurlconnection"); 

    /** THIS IS WHERE YOU SET MAKE THE NEW REQUEST TO UIWebView, which will use the new saved auth info **/ 

    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:]]; 

    [_webView loadRequest:urlRequest]; 
} 

- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection; 
{ 
    return NO; 
} 
+2

No funciona con POST. Incluso una simple modificación de esto aún no funciona con los POST. –

+2

Esto no funciona para ninguna solicitud no autenticada (_authed always == NO y se activa un ciclo infinito). Incluso si resuelve ese problema, esto aún no funciona porque shouldStartLoadWithRequest se activa varias veces por página web, lo que finalmente da como resultado que la última solicitud de URL que carga la vista web sea el único contenido que se muestra en la vista web. – Zach

+1

agrega '_authed = YES' a didReceiveResponse. Esto evita el bucle infinito cuando el servidor no envió la solicitud de desafío por algún motivo. – Seunghoon

4

como usted sabe, UIWebView no brinda la oportunidad de comunicarse con el servidor. Resolví este problema de esta manera: en el método delegado shouldStartLoadWithRequest de UIWebView I iniciando otra conexión con NSURLConnection, y ya en el método del delegado NSURLConnection didReceiveAuthenticationChallenge procesó el desafío desde el servidor. Y en el método didReceiveResponse (si surgió el desafío), de nuevo en el mismo UIWebView carga la misma URL (el desafío ya se ha procesado :). No olvide cancelar la conexión en didReceiveResponse, de lo contrario duplicará el tráfico.

+2

Si ya ha recibido la respuesta, ¿cómo la cancelación de la conexión impide duplicar el tráfico? – Travis

1

si usted está experimentando síntomas de lo que Zach describe en los comentarios de la respuesta de Sahil:

como Y5H dijo así, agrega `_authed = YES' para el método didReceiveResponse que detendrá el bucle infinito. incluso si la autenticación no fue exitosa, debe tratarla como si hubiera sido autenticada, por lo que intentará continuar cargando la página si no se requiere autenticación, si realmente se requiere autenticación, entonces fallará como siempre.

para el segundo síntoma donde el shouldStartLoadWithRequest: dispara varias veces (debido al contenido incrustado en la página web) y que sólo se mostrará lo último que se carga y no toda la página Web, haga lo siguiente:

en el shouldStartLoadWithRequest: método, añadir esto a la parte superior

if(webview.loading){ //if url requests come through while its loading, its probably embedded content 
    return YES; 
} 

edición: este método anterior tiene problemas si la página se cargue completamente, y luego cargas más contenido incrustado después, rompe con facebook el que se ve el único caso que he hasta ahora

Esto permitirá que las URL pasen mientras el sitio web está intentando cargar. No estoy seguro de si es seguro suponer que cada url después de la solicitud inicial es contenido incrustado, pero para mi propósito, pareció funcionar, por lo que tal vez sea también para usted.

También, el uso

- (void) connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 

porque

connection:canAuthenticateAgainstProtectionSpace: 
connection:didReciveAuthenticationChallenge: 
connection:didCancelAuthenticationChallenge: 

están depricated, y para mí, que no podían autenticarse con sitios web https usarlos

4

También puede proporcionar sus credenciales en el url. Simplemente agregue nombre de usuario y contraseña entre 'http: //' y 'url de la página'.

NSString *urlString = @"http://username:[email protected]/home"; 
[webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]]; 
+0

¿Qué tan seguro es esto? –

+1

Alguien en la misma red podría ver la solicitud en claro. => El uso de https con un certificado SSL resolvería este problema. Puedes verificarlo con un sniffer como Wireshark. –

0

me gustaría sugerir otra respuesta utilizando la siguiente vaina: https://github.com/jivesoftware/JiveAuthenticatingHTTPProtocol

contiene un ejemplo que muestra cómo utilizar un UIAlertView preguntar al usuario la contraseña, y se pueden adaptar fácilmente para volver una contraseña guardada de un DB local, por ejemplo.

Descargo de responsabilidad: de ninguna manera estoy afiliada con Jive ni he estado alguna vez, esto es solo una sugerencia de una herramienta que me ayudó después de luchar durante días en esto.

Cuestiones relacionadas