我一直在搜索stackoverflow,谷歌,苹果和其他地方。提供的提示看起来很有前途,我实现了它们但总的来说似乎没有工作或得到强制执行。
问题:我有NSURLConnection
具有特定凭据。然后我退出登录,清除凭据,保护空间,我删除所有缓存的响应并删除sharedHTTPCookieStorage
中的所有cookie但几秒钟后再次调用我的身份验证请求,即使使用了错误的凭据我还在使用旧(已删除)凭据
以下是一些代码摘录,其中删除了凭据
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添加一个“#”以强制执行重新认证,这可以解决问题,因为我需要依靠会话的凭据和使用完全不同的凭据的能力。
这是一个错误或已知问题,我该如何解决这个问题...... 直言不讳:我在这里做错了什么?
这真让我烦恼,不让我继续工作。
我非常感谢任何输入!
非常感谢!
答案 0 :(得分:7)
不幸的是,似乎没有解决这个问题的方法。
您可以使用NSURLCredentialPersistenceNone或#技巧,也可以定义'connectionShouldUseCredentialStorage'委托方法以返回NO。如果您每次都这样做并且您的应用程序永远不会保留会话的凭据,那么将强制在每个请求上发生挑战。
对于仅执行最少请求或最终使用会话cookie进行身份验证的应用,这可能正常。
对于发送大量请求的应用,这些解决方案都会针对每个请求产生401响应,并且额外的质询响应可以在数据和性能方面加起来。
如果您可以保留会话的凭据存储,直到您需要注销然后切换到其中一种解决方案,那将是很好的,但这是不可能的。
只要为会话存储一次凭据,就会为整个TLS会话缓存它们。这导致需要等待大约10分钟,直到该会话消失。
您可以在http://developer.apple.com/library/ios/qa/qa1727/_index.html
了解有关此问题的更多信息该文件提到了一种有限的解决方法,即附加'。'到服务器名称的末尾。然而,我一直无法做到这一点。
除此之外,这些是我能想到的解决方案:
1)始终使用NSURLCredentialPersistenceNone& connectionShouldUseCredentialStorage应该生成401s的变通方法。自己将基本身份验证标头添加到请求中。这应该可以防止额外的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。祝你好运:>)
答案 1 :(得分:4)
我刚用AFNetworking遇到了这个问题。我正在使用需要在标头中传递授权的后端。但是,当用户退出应用程序并尝试重新登录时(即使使用不同的信用卡),我从服务器收到错误。我的解决方案是在注销时清除authheader时清除我的应用程序cookie。
- (void)clearAuthorizationHeader {
[self.manager.requestSerializer clearAuthorizationHeader];
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [storage cookies]) {
[storage deleteCookie:cookie];
}
}
答案 2 :(得分:3)
我也遇到过这个问题。清除NSURLCredentialStorage
似乎部分有效,但似乎我必须在此之后等待几秒钟才能生效。在不等待的情况下执行另一个HTTP请求会导致使用旧的Authorization标头。
我可以在初始化NSURLCredentialPersistenceNone
时传递NSURLCredential
来修复它:
NSURLCredential* credentials = [[NSURLCredential alloc] initWithUser:username password:password persistence:NSURLCredentialPersistenceNone];
注意:这会对您使用此NSURLCredential
发出的每个HTTP请求导致401质询。但是,如果您找回一些可以让您通过身份验证的cookie,这不是问题。
答案 3 :(得分:1)
对于它的价值,我遇到了同样的问题。
我认为这是一个时间问题。使用模拟器时,如果我在尝试再次登录前等待5-10秒,则登录失败。此外,当我使用实际的手机时,我很少发生问题 - 这可能是手机速度较慢的一个功能,或者可能是模拟器中的错误。
答案 4 :(得分:1)
我知道这是一个古老的话题。然而,对我来说唯一有用的是为不同的证书使用不同的URL。
它在我的应用程序中起作用,因为我只有2个证书(一个是应用程序资源的常规证书,另一个是用户验证过程后从Internet下载的自定义证书)。在我的情况下,没有cookie,也没有要清除的凭据,因此我在stackoverflow上找不到任何解决方案。
答案 5 :(得分:0)
我遇到了同样的问题,现在可以了。
使用NSURLConnection
可以通过在网址末尾添加随机数来轻松解决此问题:
因此,请搜索您的URLRequest
并将随机数附加到URLRequest
NSInteger randomNumber = arc4random() % 999;
NSString *requestURL = [NSString stringWithFormat:@"%@?cache=%ld",yourURL,(long)randomNumber];
NSURL *URLRequest = [NSURL URLWithString:requestURL];
并确保在您呼叫的所有网址的末尾都有一个随机数。