iOS NTLM認証を組み込む

BASIC認証SSL認証も合わせて NTLM認証も対応しようとすると、
かなり長いコードが必要なる。

準備として、NSURLAuthenticationChallenge を一時保存できるようにしておくことで
OSによる呼ばれるメソッドの差を吸収させる。

@property (nonatomic, retain) NSURLAuthenticationChallenge* myChallenge;
@synthesize myChallenge;


そして、各々のメソッド。。。

#pragma -
#pragma mark ---- for  iOS ~4.x  ----

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
    return YES;
}

#pragma mark ---- for  iOS ~4.x  ----
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    [self authProcess:challenge];
}

#pragma mark ---- iOS 5.x~ ----
-( void ) connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    [self authProcess:challenge];
}

static BOOL isRequire_USER_PASS;

#pragma mark ---- OS共通 -------
-(void)authProcess:(NSURLAuthenticationChallenge *)challenge
{
    self.myChallenge = challenge;
    isRequire_USER_PASS = NO;
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic]
        || [challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPDigest]
        || [challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodDefault]) {
        // BASIC or DIGEST認証
        isRequire_USER_PASS = YES;
        [self performSelectorOnMainThread:@selector(challengeBasicOrNTLM) withObject:nil waitUntilDone:YES];
        return;
    }else if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodNTLM]){
        // NTLM認証
        isRequire_USER_PASS = YES;
        [self performSelectorOnMainThread:@selector(challengeBasicOrNTLM) withObject:nil waitUntilDone:YES];
    }else if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]){
        // SSL認証
        NSURLResponse *checkresponse;
        NSError *error = nil;
        [NSURLConnection sendSynchronousRequest:self.request
                              returningResponse:&checkresponse
                                          error:&error ];
        if (error==nil) {
            // 事前チェックでエラーなし
            [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]
                 forAuthenticationChallenge:challenge];
            [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
        }else{
            [self performSelectorOnMainThread:@selector(conectAlert:)
                                       withObject:[error localizedDescription]
                                    waitUntilDone:YES];
        }
    }else{
        // 対応しない認証の場合、リジェクト
        [[challenge sender] rejectProtectionSpaceAndContinueWithChallenge:challenge];
    }
}

#pragma mark ----Basic  Or  NTLM  ----
-(void)challengeBasicOrNTLM
{
    NSString* strVersion = [[UIDevice currentDevice] systemVersion];
    double version = [strVersion doubleValue];    
    if (version >= 5.0) {
        // iOS 5.0 ~
        UIAlertView *dialog = [[UIAlertView alloc] initWithTitle:localString(@"item_authentication_required")
                                                         message:@""
                                                        delegate:self
                                               cancelButtonTitle:localString(@"cancel")
                                               otherButtonTitles:@"OK", nil ];
        ((UILabel *)[[dialog subviews] objectAtIndex:1]).textAlignment = UITextAlignmentLeft;
        [dialog setAlertViewStyle: UIAlertViewStyleLoginAndPasswordInput];
        [dialog show];
        [dialog autorelease];
    }else{
        
        LoginPanel* login = [ LoginPanel shared ];
        [ login showWithDelegate: self title: localString( @"item_authentication_required" ) ];
    }
    
}

#pragma mark ---- for  iOS ~4.x  ----
-(void)loginPanelResponse:(LoginPanelResponse)response userid:(NSString*)user password:(NSString*)pw
{
    if( response == LoginPanelResponseOK ) {
        NSURLCredential* credential = [NSURLCredential credentialWithUser:user 
                                                                 password:pw
                                                              persistence:NSURLCredentialPersistenceForSession ];
        [[self.myChallenge sender] useCredential:credential 
                      forAuthenticationChallenge:self.myChallenge ];
        
    }else if( response == LoginPanelResponseCancel ) {
        [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:BROWSER_STOP_LOAD 
                                                                                             object:self] ];
    }
}

-(void)conectAlert:(NSString *)message
{
    UIAlertView* alert = [ [[UIAlertView alloc] initWithTitle: nil
                                                      message: message
                                                     delegate: self
                                            cancelButtonTitle: nil
                                            otherButtonTitles: @"OK", nil] autorelease ];
    ((UILabel *)[[alert subviews] objectAtIndex:0]).textAlignment = UITextAlignmentLeft;
    [alert show];
}

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
   if (isRequire_USER_PASS){
        switch (buttonIndex) {
            case 0:  // キャンセル
                [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:BROWSER_STOP_LOAD 
                                                                                                     object:self] ];
                break;
            case 1:  // GO
                ;  // ←なぜか、空の実行が必要 
                UITextField *username = [alertView textFieldAtIndex:0];
                UITextField *password = [alertView textFieldAtIndex:1];
                NSURLCredential* credential = [NSURLCredential credentialWithUser:username.text 
                                                                         password:password.text 
                                                                      persistence:NSURLCredentialPersistenceForSession ];
                [[self.myChallenge sender] useCredential:credential forAuthenticationChallenge:self.myChallenge];
                [delegate startIndicator];
                break;
        }
    }else{
        switch (buttonIndex) {
            case 0:  // キャンセル
                [[self.myChallenge sender] cancelAuthenticationChallenge:self.myChallenge];
                if (version >= 5.0) {
                    [ self.protocolConnection cancel ];
                }
                break;
            case 1:  // GO
                [self.myChallenge.sender useCredential:[NSURLCredential credentialForTrust:self.myChallenge.protectionSpace.serverTrust]
                            forAuthenticationChallenge:self.myChallenge ];
                [[self.myChallenge sender] continueWithoutCredentialForAuthenticationChallenge:self.myChallenge ];
                break;
        }
    }
}