2

这里有一个问题:我需要同时实现 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];

但它返回一个空数组。我为此奋斗了两天多,任何帮助将不胜感激!

4

0 回答 0