web-dev-qa-db-fra.com

Comment afficher le défi d'authentification dans UIWebView?

J'essaie d'accéder à un site Web sécurisé via UIWebView. Lorsque j'y accède via Safari, j'obtiens un défi d'authentification mais le même élément n'apparaît pas dans l'application UIWebView. Comment puis-je le faire apparaître?

Tous les pointeurs, exemples de code ou liens vous seront très utiles. Merci beaucoup. 

36
UVT

En fait, c'est très facile ... Je suis sûr que vous pouvez simplement afficher UIAlertView lorsque le délégué du challenge d'authentification est affiché (ou avant de charger l'URL, si vous êtes sûr que l'URL que vous cliquez sur Invite automatiquement les informations de connexion ). Quoi qu'il en soit, le truc est de créer votre propre NSURLConnection et je fais une logique pour enregistrer si le délégué d'authentification a été utilisé.

- (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;
}
36
Sahil

Vous pouvez également fournir vos informations d'identification dans l'URL . Il suffit d'ajouter le nom d'utilisateur et le mot de passe entre "http: //" et "URL de la page". 

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

comme vous le savez, UIWebView ne fournit aucune possibilité de communiquer avec le serveur. J'ai résolu ce problème de la manière suivante: dans la méthode déléguée, shouldStartLoadWithRequest de UIWebView, l'initiation d'une autre connexion avec NSURLConnection et déjà dans la méthode du délégué NSURLConnection didReceiveAuthenticationChallenge a traité le défi lancé par le serveur. Et dans la méthode didReceiveResponse (si le défi est arrivé), chargez de nouveau la même URL dans le même UIWebView (le défi a déjà été traité :). N'oubliez pas d'annuler la connexion dans didReceiveResponse, sinon le trafic sera doublé.

4
alexandrmoroz

si vous présentez des symptômes de ce que Zach a décrit dans les commentaires de la réponse de Sahil:

comme y5h l'a également dit, ajoutez `_authed = YES 'à la méthode didReceiveResponse qui arrêtera la boucle infinie. même si l'authentification n'a pas abouti, vous devez la traiter comme si elle était authentifiée. Le chargement de la page sera poursuivi si aucune authentification n'est requise. Si l'authentification était réellement requise, elle échouera normalement.

pour le deuxième symptôme où le shouldStartLoadWithRequest: se déclenche plusieurs fois (en raison du contenu incorporé sur la page Web) et qu'il ne montre que la dernière chose chargée et non la page Web entière, procédez comme suit:

dans la méthode shouldStartLoadWithRequest:, ajoutez ceci au début

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

edit: cette méthode ci-dessus a des problèmes si la page se charge complètement, puis charge plus de contenu intégré par la suite, rompt avec facebook qui est le seul cas vu jusqu'ici

cela laissera les URL passer pendant que le site tente de se charger. Je ne sais pas s'il est sûr de supposer que chaque URL postérieure à la demande initiale est un contenu incorporé, mais pour les besoins de l'utilisateur, cela semblait fonctionner, alors peut-être que ce sera également le cas pour vous.

utiliser aussi 

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

parce que

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

sont privés et, pour moi, vous ne pouviez pas vous authentifier avec les sites Web https les utilisant

1
Fonix

Je voudrais suggérer une autre réponse en utilisant le module suivant: https://github.com/jivesoftware/JiveAuthenticatingHTTPProtocol

Il contient un exemple montrant comment utiliser une variable UIAlertView pour demander le mot de passe à l'utilisateur. Il pourrait facilement être adapté pour renvoyer un mot de passe enregistré à partir d'une base de données locale, par exemple. 

Disclaimer: Je ne suis en aucun cas affilié à Jive et je ne l’ai jamais été, c’est juste la suggestion d’un outil qui m’a aidé après avoir lutté pendant des jours à ce sujet.

0
dvkch