16

我一直在搜索 stackoverflow、google、apple 和其他地方。提供的提示看起来很有希望,我实施了它们,但总体上似乎没有工作或得到执行。

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

以下是一些代码摘录,其中删除了凭据

        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];
            }
        }
    }

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

    NSURLCache *sharedCache = [NSURLCache sharedURLCache];
    [sharedCache removeAllCachedResponses];

然后我删除所有cookie

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

我也尝试过不使用 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];

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

这是一个错误还是已知问题,我该如何真正解决这个问题......坦率地说:我在这里到底做错了什么?

这真的让我很烦恼,让我无法继续我的工作。

我将不胜感激任何意见!

非常感谢!

4

6 回答 6

7

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

您可以使用 NSURLCredentialPersistenceNone 或 # 技巧,或者您可以定义“connectionShouldUseCredentialStorage”委托方法以返回 NO。如果您每次都这样做并且您的应用程序从不保留会话的凭据,那么这将迫使挑战发生在每个请求上。

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

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

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

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

您可以在以下位置阅读有关此问题的更多信息:http: //developer.apple.com/library/ios/qa/qa1727/_index.html

该文件提到了一个有限的解决方法,其中涉及附加一个“。” 到服务器名称的末尾。但是,我一直无法使其正常工作。

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

1) 始终使用应该生成 401 的 NSURLCredentialPersistenceNone 和 connectionShouldUseCredentialStorage 解决方法。自己将 Basic 身份验证标头添加到请求中。这应该可以防止出现额外的 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"] ;

我不知道这将如何用于其他身份验证方法,但我认为这是可能的。

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

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

于 2013-08-18T17:34:47.113 回答
4

我刚刚遇到了 AFNetworking 的这个问题。我正在使用需要在标头中传递授权的后端。但是,当用户退出应用程序并尝试重新登录(即使使用不同的凭据)时,我从服务器收到错误消息。我的解决方案是在注销时清除 authheader 时清除我的应用程序 cookie。

- (void)clearAuthorizationHeader {
    [self.manager.requestSerializer clearAuthorizationHeader];
    NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    for (NSHTTPCookie *cookie in [storage cookies]) {
        [storage deleteCookie:cookie];
    }
}
于 2015-01-13T04:53:58.443 回答
3

我也遇到过这个问题。清除NSURLCredentialStorage似乎部分有效,但似乎我必须在此之后等待几秒钟才能生效。在不等待的情况下执行另一个 HTTP 请求会导致使用旧的 Authorization 标头。

我能够NSURLCredentialPersistenceNone在初始化我的时候通过传递来修复它NSURLCredential

NSURLCredential* credentials = [[NSURLCredential alloc] initWithUser:username password:password persistence:NSURLCredentialPersistenceNone];

注意:这将在您使用 this 发出的每个 HTTP 请求上导致 401 挑战NSURLCredential。但是,如果您取回一些保持身份验证的 cookie,这不是问题。

于 2012-07-10T20:46:56.130 回答
1

对于它的价值,我遇到了同样的问题。

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

于 2011-10-06T01:51:48.190 回答
1

我知道这是一个老话题。然而,唯一对我有用的是对不同的证书使用不同的 url。

它在我的应用程序中有效,因为我只有 2 个证书(一个是应用程序资源中的通用证书,一个是在用户验证过程后从 Internet 下载的自定义证书)。在我的情况下,没有 cookie,也没有要清除的凭据,所以我在 stackoverflow 上找到的解决方案都不起作用。

于 2013-02-15T10:10:53.907 回答
0

我遇到了同样的问题,现在可以了。

通过NSURLConnection在 URL 的末尾添加一个随机数可以轻松解决此问题:

因此,搜索您的URLRequest并将随机数附加到URLRequest

NSInteger randomNumber = arc4random() % 999;
NSString *requestURL = [NSString stringWithFormat:@"%@?cache=%ld",yourURL,(long)randomNumber];

NSURL *URLRequest = [NSURL URLWithString:requestURL];

并确保在您调用的所有 URL 的末尾都有一个随机数。

于 2016-09-09T18:22:01.027 回答