我正在使用 NSURLAuthenticationChallenge 通过我的应用程序登录到网络服务器。服务器只需要一个用户名和一个密码。这是正在发生的事情:
(1) Ping 服务器的 POST 消息在 HTML 标头中包含 User-Agent 字符串
(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 和所有凭据来解决上述问题。这三种方法的代码如下:
- (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];
}
另一个问题:如果我在应用程序运行时向服务器发送消息请求之间等待很长时间,服务器会认为我已经注销并表现出与上述相同的行为。
编辑:这第二个问题仍未解决。附加信息 - 神奇的时间滞后数字似乎是 10 秒。换句话说,如果我在服务器对我进行身份验证以从服务器请求文件后等待超过 10 秒,它就无法识别我的请求,而是向我发送 Web 登录页面,就像它对未经身份验证的请求所做的那样.
知道发生了什么吗?不,我不能简单地在我的应用程序中加载网络服务器登录页面,因为这不符合这个项目的要求。