无法使用不同的NSURLCredentials重新进行身份验证(使用旧的已删除的NSURLCredentials)

Mik*_*e F 16 cocoa objective-c nsurlconnection nsurlcredential

我一直在搜索stackoverflow,谷歌,苹果和其他地方.提供的提示看起来很有前途,我实现了它们但总的来说似乎没有工作或得到强制执行.

问题:我有一个NSURLConnection具有特定凭据.然后我有一个注销,我清除凭据,保护空间,我删除所有缓存的响应并删除所有的cookie sharedHTTPCookieStorage但几秒钟后再次调用我的身份验证请求,即使有错误的凭据我仍然使用旧(已删除)凭据

以下是一些代码提取,其中删除了凭据

        NSDictionary *credentialsDict = [[NSURLCredentialStorage sharedCredentialStorage] allCredentials];

    if ([credentialsDict count] > 0) {
        // the credentialsDict has NSURLProtectionSpace objs as keys and dicts of userName => NSURLCredential
        NSEnumerator *protectionSpaceEnumerator = [credentialsDict keyEnumerator];
        id urlProtectionSpace;

        // iterate over all NSURLProtectionSpaces
        while (urlProtectionSpace = [protectionSpaceEnumerator nextObject]) {
            NSEnumerator *userNameEnumerator = [[credentialsDict objectForKey:urlProtectionSpace] keyEnumerator];
            id userName;

            // iterate over all usernames for this protectionspace, which are the keys for the actual NSURLCredentials
            while (userName = [userNameEnumerator nextObject]) {
                NSURLCredential *cred = [[credentialsDict objectForKey:urlProtectionSpace] objectForKey:userName];
                WriteLog(@"Method: switchView removing credential %@",[cred user]);
                [[NSURLCredentialStorage sharedCredentialStorage] removeCredential:cred forProtectionSpace:urlProtectionSpace];
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后我删除所有缓存的响应

    NSURLCache *sharedCache = [NSURLCache sharedURLCache];
    [sharedCache removeAllCachedResponses];
Run Code Online (Sandbox Code Playgroud)

然后我删除所有cookie

    NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    NSArray *cookies = [cookieStorage cookies];
    for (NSHTTPCookie *cookie in cookies) {
        [cookieStorage deleteCookie:cookie];
        NSLog(@"deleted cookie");
    }
Run Code Online (Sandbox Code Playgroud)

我也尝试过不使用cookie和其他政策

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:theURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0];
[request setHTTPShouldHandleCookies:NO];
if(self.currentCookies != nil){
    [request setAllHTTPHeaderFields:
     [NSHTTPCookie requestHeaderFieldsWithCookies:nil]];
}

theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
Run Code Online (Sandbox Code Playgroud)

我也在这里尝试了这个提示,专门存储cookie并再次传递它们.http://www.hanspinckaers.com/multiple-nsurlrequests-with-different-cookies.网上还有另一个博客建议为每个URL添加一个"#"以强制执行重新认证,这可以解决问题,因为我需要依靠会话的凭据和使用完全不同的凭据的能力.

这是一个错误或已知问题,我如何真正解决这个问题......直言不讳:我在这里做错了什么?

这真让我烦恼,让我继续工作.

我非常感谢任何输入!

非常感谢!

Ric*_*ers 7

不幸的是,似乎没有解决这个问题的方法.

您可以使用NSURLCredentialPersistenceNone或#技巧,也可以定义'connectionShouldUseCredentialStorage'委托方法以返回NO.如果您每次都这样做并且您的应用永远不会保留会话的凭据,那么将强制在每个请求上发生挑战.

对于仅执行最少请求或最终使用会话cookie进行身份验证的应用程序,这可能正常.

对于发送大量请求的应用程序,这些解决方案都会针对每个请求产生401响应,并且额外的质询响应可以在数据和性能方面加起来.

如果您可以保留会话的凭据存储,直到您需要注销然后切换到其中一种解决方法,那将是很好的,但这是不可能的.

只要您为会话存储一次凭据,就会为整个TLS会话缓存它们.这导致需要等待大约10分钟,直到该会话消失.

您可以在以下网址了解有关此问题的更多信息:http://developer.apple.com/library/ios/qa/qa1727/_index.html

该文件提到了一种有限的解决方法,即附加一个'.' 到服务器名称的末尾.然而,我一直无法做到这一点.

除此之外,这些是我能想到的解决方案:

1)始终使用应生成401的NSURLCredentialPersistenceNone和connectionShouldUseCredentialStorage解决方法.自己将基本身份验证标头添加到请求中.这应该可以防止额外的401,同时绕过凭证存储.添加该授权的代码如下所示:

    NSString *s ;
    NSString *authStr ;
    s = [NSString stringWithFormat:@"%@:%@",user,password] ;
    s = [YourBase64Encoder base64EncodingForData:[NSData dataWithBytes:[s UTF8String] length:strlen([s UTF8String])]];
    authStr = [NSString stringWithFormat:@"Basic %@",s] ;        
    [request setValue:authStr forHTTPHeaderField:@"Authorization"] ;
Run Code Online (Sandbox Code Playgroud)

我不知道如何为其他身份验证方法实现这一点,但我认为这是可能的.

2)通知用户该问题并要求他们重新启动应用程序

3)实现自己的基于http的检索机制的低级套接字,完全绕过CFNetwork.祝你好运:>)


小智 1

就其价值而言,我也遇到了同样的问题。

我认为这是一个时间问题。使用模拟器时,如果我等待 5-10 秒再尝试再次登录,则会按预期登录失败。另外,当我使用实际的手机时,我很少会出现问题 - 这可能是手机速度较慢的功能,或者可能是模拟器中的错误。