Как отобразить вызов аутентификации в UIWebView?

Я пытаюсь получить доступ к безопасному веб-сайту через UIWebView. Когда я обращаюсь к нему через сафари, я получаю запрос на аутентификацию, но он не отображается в моем UIWebView в приложении. Как мне сделать так, чтобы оно появилось?

Любые указатели, пример кода или ссылки будут очень полезны. Большое спасибо.


person UVT    schedule 20.11.2009    source источник


Ответы (5)


На самом деле это очень просто ... Я уверен, что вы можете просто показать UIAlertView, когда отображается делегат запроса аутентификации (или до загрузки URL-адреса, если вы точно знаете, что URL-адрес, который вы нажимаете, будет запрашивать информацию для входа в систему) ). В любом случае, уловка состоит в том, чтобы создать свой собственный NSURLConnection, и я использую некоторую логику, чтобы сохранить, использовался ли делегат аутентификации.

- (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;
}
person Sahil    schedule 08.06.2010
comment
Не работает с POST-сообщениями. Даже простая модификация этого по-прежнему не работает с POST. - person Wayne Hartman; 16.10.2010
comment
Это не работает для любых запросов без аутентификации (_authed always == NO и запускается бесконечный цикл). Даже если вы исправите эту проблему, это все равно не сработает, потому что shouldStartLoadWithRequest запускается несколько раз для каждой веб-страницы, что в конечном итоге приводит к тому, что последний запрос URL-адреса, загружаемый веб-представлением, является единственным контентом, отображаемым в веб-представлении. - person Zach; 22.04.2011
comment
добавьте '_authed = YES' в didReceiveResponse. Это предотвращает бесконечный цикл, когда сервер по какой-то причине не отправляет запрос вызова. - person Seunghoon; 11.10.2011
comment
В ответе есть пара проблем, но он дает базовую концепцию решения проблемы для аутентифицированных запросов. - person DBD; 22.08.2012
comment
Похоже, что когда соединение прерывается, данные аутентификации теряются, а _authed по-прежнему YES, и нет возможности снова выполнить аутентификацию. - person Wei Liu; 24.02.2013
comment
Этот код сработал для вас. Потому что сейчас у меня такая же проблема. Csn пожалуйста несколько ссылок или более понятное. - person Ganesh G; 24.05.2013
comment
+1 @Sahil, работает. Но мне нужно динамически устанавливать учетные данные. Является ли это возможным? - person Ganesh G; 24.05.2013
comment
@ G.Ganesh Это работает эффективно? Похоже, это вызовет два обращения к серверу при доступе к незащищенному ресурсу (поскольку, когда вы получаете ответ, вы сразу же снова вызываете loadRequest). - person Travis; 23.10.2013
comment
Должен быть способ получше ... Линия утечки памяти все портит, когда я пытаюсь использовать NSURLConnection на другой вкладке в контроллере панели вкладок. - person mafiOSo; 27.02.2014
comment
Если вы используете WKWebView, справитесь с проблемой в WKNavigationDelegate func webView(webView: WKWebView, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) - person ethanhuang13; 24.02.2016

Вы также можете указать свои учетные данные в URL-адресе. Просто добавьте имя пользователя и пароль между http: // и URL страницы.

NSString *urlString = @"http://username:[email protected]/home";
[webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]];
person Mickael West    schedule 20.02.2014
comment
Кто-то в той же сети мог ясно видеть запрос. = ›Использование https с сертификатом SSL решило бы эту проблему. Вы можете проверить это с помощью сниффера, такого как Wireshark. - person Mickael West; 12.09.2014

как известно, UIWebView не предоставляет возможности общаться с сервером. Я решил эту проблему так: в методе делегата shouldStartLoadWithRequest интерфейса UIWebView я инициировал другое соединение с NSURLConnection, и уже в методе делегата NSURLConnection didReceiveAuthenticationChallenge обработал запрос с сервера. А в методе didReceiveResponse (если пришел вызов) снова в том же UIWebView загружаем тот же URL (запрос уже обработан :). Не забудьте отменить соединение в didReceiveResponse, иначе он удвоит трафик.

person alexandrmoroz    schedule 26.12.2009
comment
Если вы уже получили ответ, как отмена соединения предотвратит удвоение трафика? - person Travis; 23.10.2013

если вы испытываете симптомы того, что Зак описал в комментариях к ответу Сахила:

как также сказал y5h, добавьте `_authed = YES 'к методу didReceiveResponse, который остановит бесконечный цикл. даже если аутентификация не была успешной, вам нужно относиться к ней так, как если бы она была аутентифицирована, поэтому он попытается продолжить загрузку страницы, если аутентификация не требуется, если аутентификация действительно требовалась, тогда она просто потерпит неудачу, как обычно.

для второго симптома, когда shouldStartLoadWithRequest: срабатывает несколько раз (из-за встроенного содержимого на веб-странице), и он просто покажет последнее загруженное, а не всю веб-страницу, сделайте следующее:

в методе shouldStartLoadWithRequest: добавьте это в начало

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

edit: этот метод выше имеет проблемы, если страница полностью загружается, а затем загружает больше встроенного контента, прерывается с facebook, который является единственным случаем, который я видел до сих пор

это позволит URL-адресам проходить, пока веб-сайт пытается загрузиться. Я не уверен, можно ли предположить, что каждый URL-адрес после первоначального запроса представляет собой встроенный контент, но для моих целей это, похоже, сработало, так что, возможно, это будет и для вас.

также используйте

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

так как

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

являются устаревшими, и для меня вы не могли аутентифицироваться на https-сайтах, используя их

person Fonix    schedule 18.07.2013

Я хотел бы предложить другой ответ, используя следующий модуль: https://github.com/jivesoftware/JiveAuthenticatingHTTPProtocol

Он содержит пример, показывающий, как использовать UIAlertView для запроса пароля у пользователя, и может быть легко адаптирован, например, для возврата сохраненного пароля из локальной БД.

Отказ от ответственности: я никоим образом не связан с Jive и никогда не был, это просто предложение инструмента, который помог мне после нескольких дней борьбы с этим.

person dvkch    schedule 12.10.2015