2

我正在使用 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 登录页面,就像它对未经身份验证的请求所做的那样.

知道发生了什么吗?不,我不能简单地在我的应用程序中加载网络服务器登录页面,因为这不符合这个项目的要求。

4

0 回答 0