2009-11-20 10 views
36

Sto tentando di accedere a un sito Web protetto tramite UIWebView. Quando accedo tramite safari, ottengo una richiesta di autenticazione ma lo stesso non appare nel mio UIWebView nell'applicazione. Come posso farlo apparire?Come visualizzare la sfida di autenticazione in UIWebView?

Qualsiasi suggerimento, codice di esempio o collegamenti sarà molto utile. Molte grazie.

risposta

35

È davvero super facile ... Sono sicuro che puoi solo mostrare un UIAlertView quando viene mostrato il delegato di autenticazione auth (o prima di caricare l'URL, se sei sicuro che l'URL che stai colpendo ti verrà richiesto per informazioni di accesso auth). In ogni caso, il trucco è creare il proprio NSURLConnection e faccio qualche logica per salvare se è stato utilizzato il delegato di autenticazione.

- (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

Non funziona con i POST. Anche una semplice modifica di questo non funziona ancora con i POST. –

+2

Questo non funziona per nessuna richiesta non autenticata (_authed always == NO e viene attivato un ciclo infinito). Anche se correggi il problema, questo non funziona perché shouldStartLoadWithRequest viene generato più volte per ogni pagina web che alla fine risulta nell'ultima richiesta di URL che la visualizzazione web viene caricata come unico contenuto visualizzato nella visualizzazione web. – Zach

+1

aggiungi '_authed = YES' a didReceiveResponse. Questo impedisce loop infinito quando il server non ha inviato richiesta di sfida per qualche motivo. – Seunghoon

4

come sapete, UIWebView non offre opportunità di comunicare con il server. Ho risolto questo problema in questo modo: nel metodo delegato shouldStartLoadWithRequest di UIWebView ho iniziato un'altra connessione con NSURLConnection, e già nel metodo del delegato NSURLConnection didReceiveAuthenticationChallenge ha elaborato il server dal server. Nel metodo ha fattoReceiveResponse (se la sfida è arrivata), poi di nuovo nella stessa UIWebView caricare lo stesso URL (la sfida è già stata elaborata :). Non dimenticare di annullare la connessione in didReceiveResponse, altrimenti raddoppierà il traffico.

+2

Se la risposta è già stata ricevuta, in che modo l'annullamento della connessione impedisce il raddoppio del traffico? – Travis

1

se si verificano i sintomi di ciò che Zach ha descritto nei commenti di risposta di Sahil:

come Y5H detto così, aggiunge `_authed = YES' per il metodo didReceiveResponse che fermare il loop infinito. anche se l'autenticazione non ha avuto successo, è necessario trattarla come se fosse autenticata, quindi proverà a caricare la pagina se non è richiesta l'autenticazione, se l'autenticazione è veramente necessaria, quindi fallirà come normale.

per il secondo sintomo dove lo shouldStartLoadWithRequest: spara più volte (a causa di contenuto incorporato sulla pagina web) e sarà solo mostrare l'ultima cosa che ha caricato e non l'intera pagina web, fare questo:

nel shouldStartLoadWithRequest: metodo, aggiungere questo alla parte superiore

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

edit: questo metodo di cui sopra ha problemi se la pagina completamente carichi, e poi carichi contenuti più incorporato in seguito, rompe con facebook, che è l'unico caso ive visto finora

consentirà agli URL di accedere mentre il sito Web tenta di caricare. Non sono sicuro che sia sicuro assumere che ogni url dopo la richiesta iniziale è contenuto incorporato, ma per i miei scopi sembra funzionare, quindi forse lo sarà anche per te.

Inoltre, utilizzare

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

perché

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

sono depricated, e per me, non si poteva autenticazione con https siti web che li utilizzano

4

È possibile anche fornire le proprie credenziali nella url. Basta aggiungere username e password tra "http: //" e "page url".

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

Quanto è sicuro? –

+1

Qualcuno sulla stessa rete potrebbe vedere la richiesta in chiaro. => L'uso di https con un certificato SSL risolverebbe questo problema. Puoi verificarlo con uno sniffer come Wireshark. –

0

vorrei suggerire un'altra risposta utilizzando il seguente pod: https://github.com/jivesoftware/JiveAuthenticatingHTTPProtocol

contiene un esempio che mostra come utilizzare un UIAlertView chiedere all'utente la password, e potrebbe essere facilmente adattato per tornare per esempio una password salvata da un DB locale.

Disclaimer: Io non sono in alcun modo affiliato con Jive né lo sono mai stato, questo è solo un suggerimento di uno strumento che mi ha aiutato dopo aver lottato per giorni su questo.

Problemi correlati