error codes ios authentication nsurlconnection

ios - codes - swift http request



AutenticaciĆ³n con NSURLConnection sendAsynchronousRequest con controlador de finalizaciĆ³n (3)

Aunque el problema se resuelve hace un tiempo, quiero agregar una solución que no requiera bibliotecas de terceros:

//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.. }

En general, me gusta simplemente "disparar y olvidar" con el método de clase sendAsynchronousRequest de NSURL utilizando el bloque de controlador de finalización, pero parece que podría no ser una opción cuando se necesita autenticación.

Cuando se utiliza una solicitud de estilo de controlador de finalización como esta:

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

¿Cuál es la forma correcta de manejar la autenticación? ¿Debo asignar alloc e init NSURLConnection y establecer un delegado en lugar de utilizar este estilo de método de clase? Creo que entiendo cómo autenticarme correctamente con la función de delegado, pero estoy tratando de averiguar si puedo incluir eso en el bloque de finalizaciónHandler o si hay una mejor manera de hacerlo.

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


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


Creo que el método completionHandler es para solicitudes básicas. Tal vez podría considerar usar AFNetworking ya que lo uso con métodos de bloqueo y autenticación.

EDIT .... ¿Has intentado agregar el encabezado de autenticación a NSURLRequest? Crea una NSMutableURLRequest:

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

Y agregue el encabezado de autenticación de esta manera:

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

La función AFBase64EncodedStringFromString es esta:

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[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 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]; }

Luego llame a la función que llamó anteriormente, pero utilizando su nueva solicitud de NSURL:

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