NSURLAuthenticationChallenge を使用して、アプリから Web サーバーにログインしています。サーバーが必要とするのは、ユーザー名とパスワードだけです。何が起こっているかは次のとおりです。
(1) HTML ヘッダーに User-Agent 文字列を含む POST メッセージでサーバーに ping を実行する
(2) サーバーは、 didReceiveAuthenticationChallengeデリゲート メソッドによって検出される認証チャレンジで応答します。
(3) ユーザー名とパスワードを使用してチャレンジ応答を送信して応答します。
NSURLCredential *cred = [[NSURLCredential alloc] initWithUser:unameTextField.text
password:pswdTextField.text
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:cred forAuthenticationChallenge:challenge];
(4) ユーザー名/パスワードが正しい場合、デリゲート メソッドconnectionDidFinishLoadingが呼び出され、チャレンジ レスポンスがサーバーによって受け入れられたことを検出します。ユーザーはログインし、サーバーからメッセージを送受信できます。(ユーザー名/パスワードが正しくない場合、デリゲート メソッドdidFailWithErrorが呼び出され、ユーザーにアラートが表示されます。)
ここで問題が発生します。最初に Xcode プロジェクトを開いてアプリを実行し、正しいユーザー名/パスワードでログインしようとすると、ステップ 3 と 4 の間に 10 ~ 15 秒のタイムラグがあります。connectionDidFinishLoadingが呼び出され、サーバーにファイルを要求するメッセージを送信すると、認証されていない要求のデフォルトの動作である HTML ログインページを送信して応答します...結局ログインしていないようです。
アプリを停止してから再度実行すると、遅延はなく、すべて正常に動作します。
編集:各ログイン試行の前に、URLCache、すべての Cookie、およびすべての資格情報をクリアすることで、上記の問題を解決しました。これら 3 つのメソッドのコードは次のとおりです。
- (void)clearCookiesForURL
{
NSURL *loginUrl = [NSURL URLWithString:@"https://www.MYURL.com"];
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSArray *cookies = [cookieStorage cookiesForURL:loginUrl];
for (NSHTTPCookie *cookie in cookies)
{
[cookieStorage deleteCookie:cookie];
}
}
- (void)eraseCredentials
{
NSString *urlString = @"www.MYURL.com";
NSURLCredentialStorage *credentialsStorage = [NSURLCredentialStorage sharedCredentialStorage];
NSDictionary *allCredentials = [credentialsStorage allCredentials];
if ([allCredentials count] > 0)
{
for (NSURLProtectionSpace *protectionSpace in allCredentials)
{
if ([[protectionSpace host] isEqualToString:urlString])
{
NSDictionary *credentials = [credentialsStorage credentialsForProtectionSpace:protectionSpace];
for (NSString *credentialKey in credentials)
{
[credentialsStorage removeCredential:[credentials objectForKey:credentialKey] forProtectionSpace:protectionSpace];
}
}
}
}
}
- (void)eraseURLCache
{
NSURL *loginUrl = [NSURL URLWithString:@"https://www.MYURL.com"];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:loginUrl];
[[NSURLCache sharedURLCache] removeCachedResponseForRequest:urlRequest];
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
}
もう 1 つの問題: アプリの実行中にメッセージ リクエストをサーバーに送信するまでに長い時間待機すると、サーバーはユーザーがログアウトしたと見なし、上記と同じ動作を示します。
編集: この 2 番目の問題は未解決のままです。追加情報 - マジック タイム ラグ数は 10 秒のようです。つまり、サーバーが認証してから 10 秒以上待ってからファイルを要求すると、サーバーは要求を認識せず、認証されていない要求の場合と同様に、代わりに Web ログイン ページを送信します。 .
何が起こっているのか分かりますか?いいえ、このプロジェクトの要件を満たしていないため、アプリ内に Web サーバーのログイン ページをロードすることはできません。