2009-11-20 21 views
36

私はUIWebViewを通じて安全なウェブサイトにアクセスしようとしています。 Safariを使用してアクセスすると、認証の問題が発生しますが、アプリケーションのUIWebViewには表示されません。どうすればそれを表示させることができますか?UIWebViewで認証チャレンジを表示する方法は?

ポインタ、サンプルコード、またはリンクは非常に役に立ちます。どうもありがとう。

答えて

35

実際には非常に簡単です...認証チャレンジデリゲートが表示されているとき(または、URLをロードする前に、あなたが叩いているURLがプロンプトを表示していることがわかっている場合は、UIAlertViewを表示できます認証情報の認証用)。とにかく、自分の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; 
} 
+2

POSTでは動作しません。これを単純に変更してもPOSTでは動作しません。 –

+2

これは認証されていない要求(_authedは常に== NO、無限ループがトリガーされます)では機能しません。その問題を解決してもshouldStartLoadWithRequestがWebページごとに複数回起動されるため、最終的にWebビューがロードする最後のURL要求がWebビューに表示される唯一のコンテンツになるため、この問題は解決しません。 – Zach

+1

didReceiveResponseに '_authed = YES'を追加します。これにより、何らかの理由でサーバーがチャレンジ要求を送信しなかった場合、無限ループが発生しなくなります。 – Seunghoon

4

ご存じのように、UIWebViewはサーバーと通信する機会を提供しません。 私はこのようにこの問題を解決しました。デリゲートメソッドのUIWebViewのshouldStartLoadWithRequest NSURLConnectionとの別の接続を開始し、既にデリゲートNSURLConnectionのメソッドにdidReceiveAuthenticationChallengeがサーバーからのсhallengeを処理しました。メソッドdidReceiveResponse(チャレンジが来た場合)で、同じUIWebViewで同じURLを再度ロードします(チャレンジはすでに処理されています:)。 didReceiveResponseで接続をキャンセルすることを忘れないでください。そうしないと、トラフィックが2倍になります。

+2

既に応答を受け取っている場合、接続をキャンセルするとトラフィックが倍増しないのはなぜですか? – Travis

1

あなたはザックがサヒールの答えのコメントで述べたものの症状を経験している場合:

y5hは無限ループを停止しますdidReceiveResponse方法に `_authed = YES」を追加し、同様に言ったように。 authが成功しなかったとしても、authedされたように扱う必要があるので、認証が必要な場合はページをロードし続け、認証が本当に必要な場合は通常のように失敗します。 (によるWebページ上の埋め込みコンテンツへ)を複数回発射し、それだけで、全体のWebページロードされていないが、これを行うことを最後に表示されます::で

shouldStartLoadWithRequestが第二の症状のための

shouldStartLoadWithRequest:この方法は、

トップ

if(webview.loading){ //if url requests come through while its loading, its probably embedded content 
    return YES; 
} 
にこれを追加、編集:これ以上の方法は、ページが完全にロードする場合の問題があり、その後、その後多くの埋め込みコンテンツをロードし、これまで

見た唯一のケースアイブあるFacebookので破ります

これは、ウェブサイトがロードしようとしている間にURLを通過させます。最初のリクエスト後のすべてのURLが埋め込まれたコンテンツであると想定するのが安全かどうかはわかりませんが、私の目的のためにはうまくいくと思われます。また

は、

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

は廃止予定されている

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

ので使用し、私のために、あなたはまた、中に資格情報を提供することができ

4

それらを使用してHTTPSサイトを認証できませんでしたurl。 「http://」と「page url」の間にユーザー名とパスワードを追加するだけです。

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

これはどの程度安全ですか? –

+1

同じネットワーク上にいる誰かが、その要求を明確に見ることができました。 => SSL証明書でhttpsを使用するとこの問題は解決します。 Wiresharkなどのスニファで確認できます。 –

0

私は、次のポッド使用して別の答えを提案したいと思います:それは、パスワードの入力をユーザーに要求するUIAlertViewを使用する方法を示す例が含まれており、簡単にリターンに適合させることができる https://github.com/jivesoftware/JiveAuthenticatingHTTPProtocol

を例えば、ローカルDBから保存されたパスワード。

免責事項:私はJiveと提携していないし、これまでに行ったこともありません。これは数日間苦労して私を助けたツールの提案に過ぎません。

関連する問題