iPhone - NTLM, Basic and other authorizations usin

2019-07-12 13:57发布

Here's an issue: I need to implement both HTTP basic authorization and MS NTLM authorization. I use asynchronous NSURLConnection so I receive

-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge

callback. The full code of this method looks like that:

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

The two global issues I've met so far using this method:

1) As per Charles sniffer, all the requests to the server are doubled (as per Apple Docs, it's an expected behaviour). However, it leads to lack of performance (two requests instead of just one) comparing to setting header directly, using setValue:forHTTPHeader:.

2) It's being called not for every request. For example, when I'm trying to grab an image from server, it returns 302 (redirect to login web page) HTTP code instead of 401 HTTP code, so this does not work at all.

What I want to accomplish, is to grab the correct Authorization header once and then put it manually in every subsequent NSMutableURLRequest I make. I can compose HTTP Basic authorization manually, it's pretty simple, but I can't compose NTLM header in the same manner, that's why I was relying on didReceiveAuthenticationChallenge: method.

Could you please point me out, how can I receive the Authorization header, that is set automatically by NSURLProtectionSpace, so each request will INITIALLY go authorized?

P.S. I tried to receive it from

[connection.currentRequest allHTTPHeaderFields];

but it returns an empty array. I'm fighting with that for more than two days, any help will be kindly appreciated!

0条回答
登录 后发表回答