2014-01-10 28 views
1

我正嘗試創建一個基於UIWebView的應用程序。其主要目的是爲使用NTLM或基本身份驗證的少數網站提供身份驗證,而用戶在更改密碼(網站共享用戶/密碼數據庫)時不必輸入每個網站的用戶名/密碼。當從NSURLConnectionDataDelegate設置內容時,UIWebView重新加載baseUrl

爲了做到這一點,我「覆蓋」爲UIWebView加載頁面數據,以便我可以截獲HTTP響應代碼,並在每次檢測到響應時詢問用戶密碼。

我已經建立了一個NSURLConnectionDataDelegate來處理請求這樣:

@interface LPURLConnectionDelegate : NSObject<NSURLConnectionDataDelegate> 
{ 
    UIWebView* _webView; 
    NSMutableURLRequest* _request; 
    NSURLConnection* _connection; 
    NSString* _encoding; 
    NSString* _mimeType; 
    NSMutableData* _data; 
} 

- (LPURLConnectionDelegate*) initWithWebView:(UIWebView *)webView; 

- (void) loadPageWithRequest: (NSURLRequest*)request; 

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge; 
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error; 
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response; 
- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection; 
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data; 
- (void)connectionDidFinishLoading:(NSURLConnection *)connection; 

@end 

@implementation LPURLConnectionDelegate 
- (void) loadPageWithRequest: (NSURLRequest*)request 
{ 
    _request = [request mutableCopy]; 
    if(!_data) 
    { 
     _data = [NSMutableData dataWithCapacity:0]; 
     [_data retain]; 
    } 
    [_data setLength:0]; 
    if(_connection) 
    { 
     [_connection cancel]; 
     [_connection release]; 
     _connection = nil; 
    } 
    _connection = [[NSURLConnection alloc] initWithRequest:_request delegate:self startImmediately:YES]; 
} 

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 
{ 
    LPAppDelegate* delegate = [LPAppDelegate getInstance]; 
    NSURLCredential* credential = [NSURLCredential credentialWithUser:[delegate getUsername] password:[delegate getPassword] persistence:NSURLCredentialPersistenceForSession]; 
    [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
    //handle connection failed 
} 

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{ 
    NSLog(@"Connection did receive response"); 
    NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response; 
    _mimeType = [httpResponse MIMEType]; 
    _encoding = [httpResponse textEncodingName]; 
    //handle status - if the status is 401, the connection is canceled and the user is asked for his new password 
} 

- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection 
{ 
    return YES; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    [_data appendData:data]; 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{  
    [_webView loadData:_data MIMEType:_mimeType textEncodingName:_encoding baseURL:[_request URL]]; 
} 

@end 

UIWebViewDelegate看起來是這樣的:

@interface LPWebViewDelegate : NSObject<UIWebViewDelegate> 

- (void)webViewDidStartLoad:(UIWebView *)webView; 
- (void)webViewDidFinishLoad:(UIWebView *)webView; 
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error; 
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; 

@end 


@implementation LPWebViewDelegate 

- (void) webViewDidStartLoad:(UIWebView *)webView 
{ 
} 

- (void) webViewDidFinishLoad:(UIWebView *)webView 
{ 
    //handle success 
} 

- (BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 
{ 
    LPURLConnectionDelegate* connectionDelegate = [[LPURLConnectionDelegate alloc] initWithWebView:webView]; 
    [connectionDelegate loadPageWithRequest:request]; 
    return NO; 
} 

- (void) webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error 
{ 
    //handle fail 
} 

@end 

基本上,我想要做的是告訴UIWebView不要自行加載任何頁面,讓我處理加載頁面的請求。當請求完成並且用戶通過身份驗證時,我試圖使用UIWebView::loadData:MIMEType:textEncodingName:baseUrl方法設置數據。

的這裏的問題是,從NSURLConnectionDataDelegate設置UIWebView的數據後,UIWebView重新加載頁面設置爲baseURL(至少在模擬器 - 我還沒有嘗試在實際設備上的代碼,只是還沒有)。

有沒有人知道一種方式來設置數據到UIWebView s以這樣的方式,它不會重新加載頁面(*)?我知道我可以讓UIWebViewNSURLConnection檢查身份驗證(或並行)之後加載頁面,但我試圖避免爲每個頁面請求頁面標題兩次。

注意:代碼不完整,我已經提取了我認爲是該問題最相關的部分。

回答

1

實施NSURLProtocol類。它基本上是一個抽象類,允許子類定義HTTP方案的URL加載行爲

查看本教程here

相關問題