这里有一个问题:我需要同时实现 HTTP 基本授权和 MS NTLM 授权。我使用异步 NSURLConnection 所以我收到
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
打回来。此方法的完整代码如下所示:
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSString* authMethod = [[challenge protectionSpace] authenticationMethod];
NSLog(@"Authentication method: %@", authMethod);
NSString *userName = self.login;
if ([authMethod isEqualToString:NSURLAuthenticationMethodNTLM]) {
userName = [userName lastElementAfterSlash];
}
else if ([authMethod isEqualToString:NSURLAuthenticationMethodNegotiate]) {
userName = [NSString stringWithFormat:@"%@@%@", userName, self.url.host];
}
if ([challenge previousFailureCount] <= 1) {
NSURLCredential *credential = [NSURLCredential credentialWithUser:userName password:self.password persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:[self.url host]
port:0
protocol:self.url.scheme
realm:[self.url host]
authenticationMethod:authMethod];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential
forProtectionSpace:protectionSpace];
}
else {
NSLog(@"Authentication error");
NSLog(@"Failed login with status code: %d", [(NSHTTPURLResponse*)[challenge failureResponse]statusCode]);
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
到目前为止,我使用这种方法遇到的两个全球性问题:
1)根据 Charles 嗅探器,对服务器的所有请求都加倍(根据 Apple Docs,这是预期的行为)。但是,与使用 setValue:forHTTPHeader: 直接设置标头相比,它会导致性能不足(两个请求而不是一个请求)。
2)不是每个请求都调用它。例如,当我尝试从服务器获取图像时,它返回 302(重定向到登录网页)HTTP 代码而不是 401 HTTP 代码,所以这根本不起作用。
我想要完成的是一次获取正确的 Authorization 标头,然后手动将其放入我随后创建的每个 NSMutableURLRequest 中。我可以手动编写 HTTP 基本授权,这很简单,但我不能以相同的方式编写 NTLM 标头,这就是我依赖 didReceiveAuthenticationChallenge: 方法的原因。
您能否指出我如何接收由 NSURLProtectionSpace 自动设置的 Authorization 标头,因此每个请求都会首先获得授权?
PS我试图从
[connection.currentRequest allHTTPHeaderFields];
但它返回一个空数组。我为此奋斗了两天多,任何帮助将不胜感激!