2012-10-10 10 views
12

In genere mi piace solo "attivare e disattivare" con il metodo della classe sendAsynchronousRequest di NSURL utilizzando il blocco del gestore di completamento ma sembra che potrebbe non essere un'opzione quando è necessaria l'autenticazione.Autenticazione con NSURLConnection sendAsynchronousRequest con gestore di completamento

Quando si utilizza un completamento richiesta stile handler in questo modo:

[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.mysite.com/"]] 
             queue:[NSOperationQueue mainQueue] 
          completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 


          //Do Stuff 

          }]; 

Qual è il modo corretto di gestire l'autenticazione? Devo allocare e avviare NSURLConnection e impostare un delegato invece di utilizzare questo stile del metodo di classe? Penso di capire come autenticarsi correttamente con la funzione delegate ma sto cercando di capire se posso includerlo nel blocco completionHandler o se c'è un modo migliore per farlo.

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 
{ 

    if ([challenge previousFailureCount] > 0) { 
     NSLog(@"Authentication Failure"); 
     [connection cancel]; 
    } 
    else 
    { 

     NSURLCredential *credential = [NSURLCredential credentialWithUser:self.username 
                   password:self.password 
                   persistence:NSURLCredentialPersistenceForSession]; 
     [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; 
    } 

} 

risposta

22

Penso che il metodo completionHandler sia per le richieste di base. Forse potresti prendere in considerazione l'utilizzo di AFNetworking mentre lo utilizzo con metodi di blocco e autenticazione.

MODIFICA .... Hai provato ad aggiungere l'intestazione di autenticazione a NSURLRequest? Crea un NSMutableURLRequest:

NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.example.com/"]]; 

E aggiungere l'intestazione di autenticazione in questo modo:

NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", userName, password]; 
NSString *authValue = [NSString stringWithFormat:@"Basic %@", AFBase64EncodedStringFromString(basicAuthCredentials)]; 
[urlRequest setValue:authValue forHTTPHeaderField:@"Authorization"]; 

La funzione AFBase64EncodedStringFromString è questo:

static NSString * AFBase64EncodedStringFromString(NSString *string) { 
    NSData *data = [NSData dataWithBytes:[string UTF8String] length:[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]; 
    NSUInteger length = [data length]; 
    NSMutableData *mutableData = [NSMutableData dataWithLength:((length + 2)/3) * 4]; 

    uint8_t *input = (uint8_t *)[data bytes]; 
    uint8_t *output = (uint8_t *)[mutableData mutableBytes]; 

    for (NSUInteger i = 0; i < length; i += 3) { 
     NSUInteger value = 0; 
     for (NSUInteger j = i; j < (i + 3); j++) { 
      value <<= 8; 
      if (j < length) { 
       value |= (0xFF & input[j]); 
      } 
     } 

     static uint8_t const kAFBase64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/"; 

     NSUInteger idx = (i/3) * 4; 
     output[idx + 0] = kAFBase64EncodingTable[(value >> 18) & 0x3F]; 
     output[idx + 1] = kAFBase64EncodingTable[(value >> 12) & 0x3F]; 
     output[idx + 2] = (i + 1) < length ? kAFBase64EncodingTable[(value >> 6) & 0x3F] : '='; 
     output[idx + 3] = (i + 2) < length ? kAFBase64EncodingTable[(value >> 0) & 0x3F] : '='; 
    } 

    return [[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding]; 
} 

quindi chiamare la funzione hai chiamato prima, ma utilizzando il tuo nuovo NSURLRequest:

[NSURLConnection sendAsynchronousRequest:urlRequest 
    queue:[NSOperationQueue mainQueue] 
    completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 

}]; 
+0

' AFBase64EncodedStringFromString' è un funzione privata, e non è destinato a essere utilizzato da solo. Invece, si può fare 'AFHTTPClient setAuthorizationHeaderWithUsername: password:' e creare un 'NSURLRequest' con' -requestWithMethod: path: parameters: '(o semplicemente copiare l'intestazione di autorizzazione dalla richiesta generata. – mattt

+3

Ci deve essere un modo per ottenere ciò senza Librerie di terze parti ... – dan

21

Anche se il problema è stato risolto un po 'adesso, voglio aggiungere una soluzione che doesn `t richiedono 3rd librerie di parti:

//HTTP Authentication 
NSString *authStr = [NSString stringWithFormat:@"%@:%@", @"Username", @"Password"]]; 
NSData *authData = [authStr dataUsingEncoding:NSASCIIStringEncoding]; 
NSString *authValue = [authData base64Encoding]; 

//Set up Request: 
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]init]; 
[request setURL:[NSURL URLWithString:url]]; 
//... 
// Pack in the user credentials 
[request setValue:[NSString stringWithFormat:@"Basic %@",authValue] forHTTPHeaderField:@"Authorization"]; 

// Send the asynchronous request as usual 
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *responseCode, NSData *responseData, NSError *error) { 

    // Do stuff.. 

} 
+0

Si prega di notare che questo codice ti dà un avvertimento ora 'deprecato in iOS 9'. Vedi questo post per risolvere: http://stackoverflow.com/questions/30935304/sendasynchronousrequest-was-deprecated-in-ios -9-how-to-alter-codice-a-fix – dan

1
NSURLConnection is deprecated in iOS 9, try this code which is from LazyTableImages example from here [https://developer.apple.com/library/ios/samplecode/LazyTableImages/Introduction/Intro.html][1] 
@property (nonatomic, strong) NSURLSessionDataTask *sessionTask; 



    //somwere in your code 

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] 
            initWithURL:[NSURL URLWithString:self.postLink] ]; 

    [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData]; 
    [request setHTTPShouldHandleCookies:NO]; 
    [request setTimeoutInterval:60]; 
    [request setHTTPMethod:@"POST"]; 
    [request addValue:[[NSUserDefaults standardUserDefaults] objectForKey:@"token"] 
    forHTTPHeaderField:@"ACCESSTOKEN"]; 


    self.sessionTask = [[NSURLSession sharedSession] dataTaskWithRequest:request 
                  completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
    //do completion staff here 
    }]; 
Problemi correlati