with finished error codes code ios iphone objective-c nsurlconnection

finished - NSURLConnection y Autenticación HTTP básica en iOS



nsurlconnection error codes (7)

¿Puede decirme cuál es la razón detrás de limitar la longitud de la línea de codificación a 80 en su código de ejemplo? Pensé que los encabezados HTTP tienen una longitud máxima de algo así como 4k (o tal vez algunos servidores no toman más tiempo que eso). - Justin Galzic 29 de diciembre de 2009 a las 17:29

No es una limitación de 80, es una opción del método base64EncodingWithLineLength en NSData + Base64.h / m, donde puede dividir la cadena codificada en varias líneas, lo que es útil para otras aplicaciones, como la transmisión nntp. Creo que el autor del motor de Twitter elige 80 para que sea lo suficientemente grande como para acomodar la mayoría de los resultados codificados por usuario / contraseña en una línea.

Necesito invocar una GET HTTP request inicial con Authentication básica. Esta sería la primera vez que se envía la solicitud al servidor y ya tengo el username & password por lo que no es necesario que el servidor solicite autorización.

Primera pregunta:

  1. ¿ NSURLConnection debe establecerse como síncrono para realizar Authentic básico? Según la respuesta en esta post , parece que no puedes hacer Basic Auth si optas por la ruta asíncrona.

  2. ¿Alguien sabe de algún código de muestra que ilustra la autenticación básica en una GET request sin la necesidad de una respuesta de desafío? La documentación de Apple muestra un ejemplo, pero solo después de que el servidor haya emitido la solicitud de desafío al cliente.

Soy un poco nuevo en la parte de redes del SDK y no estoy seguro de cuál de las otras clases debería usar para que funcione. (Veo la clase de NSURLCredential pero parece que solo se usa con NSURLAuthenticationChallenge después de que el cliente haya solicitado un recurso autorizado del servidor).


Aquí hay una respuesta detallada sin participación de terceros:

Por favor revisa aquí:

//username and password value NSString *username = @“your_username”; NSString *password = @“your_password”; //HTTP Basic Authentication NSString *authenticationString = [NSString stringWithFormat:@"%@:%@", username, password]]; NSData *authenticationData = [authenticationString dataUsingEncoding:NSASCIIStringEncoding]; NSString *authenticationValue = [authenticationData base64Encoding]; //Set up your request NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.your-api.com/“]]; // Set your user login credentials [request setValue:[NSString stringWithFormat:@"Basic %@", authenticationValue] forHTTPHeaderField:@"Authorization"]; // Send your request asynchronously [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *responseCode, NSData *responseData, NSError *responseError) { if ([responseData length] > 0 && responseError == nil){ //logic here }else if ([responseData length] == 0 && responseError == nil){ NSLog(@"data error: %@", responseError); UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"Error accessing the data" delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil]; [alert show]; [alert release]; }else if (responseError != nil && responseError.code == NSURLErrorTimedOut){ NSLog(@"data timeout: %@”, NSURLErrorTimedOut); UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"connection timeout" delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil]; [alert show]; [alert release]; }else if (responseError != nil){ NSLog(@"data download error: %@”,responseError); UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"data download error" delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil]; [alert show]; [alert release]; } }]

Por favor, háganme saber sus comentarios sobre esto.

Gracias


Como NSData :: dataUsingEncoding está en desuso (ios 7.0), puede usar esta solución:

// Forming string with credentials ''myusername:mypassword'' NSString *authStr = [NSString stringWithFormat:@"%@:%@", username, password]; // Getting data from it NSData *authData = [authStr dataUsingEncoding:NSASCIIStringEncoding]; // Encoding data with base64 and converting back to NSString NSString* authStrData = [[NSString alloc] initWithData:[authData base64EncodedDataWithOptions:NSDataBase64EncodingEndLineWithLineFeed] encoding:NSASCIIStringEncoding]; // Forming Basic Authorization string Header NSString *authValue = [NSString stringWithFormat:@"Basic %@", authStrData]; // Assigning it to request [request setValue:authValue forHTTPHeaderField:@"Authorization"];


Estoy usando una conexión asíncrona con MGTwitterEngine y establece la autorización en NSMutableURLRequest ( theRequest ) de esta manera:

NSString *authStr = [NSString stringWithFormat:@"%@:%@", [self username], [self password]]; NSData *authData = [authStr dataUsingEncoding:NSASCIIStringEncoding]; NSString *authValue = [NSString stringWithFormat:@"Basic %@", [authData base64EncodingWithLineLength:80]]; [theRequest setValue:authValue forHTTPHeaderField:@"Authorization"];

No creo que este método requiera pasar por el ciclo de desafío, pero podría estar equivocado


Incluso si se responde la pregunta, quiero presentar la solución, que no requiere libs externos, encontré en otro hilo:

// Setup NSURLConnection NSURL *URL = [NSURL URLWithString:url]; NSURLRequest *request = [NSURLRequest requestWithURL:URL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0]; NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; [connection start]; [connection release]; // NSURLConnection Delegates - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { if ([challenge previousFailureCount] == 0) { NSLog(@"received authentication challenge"); NSURLCredential *newCredential = [NSURLCredential credentialWithUser:@"USER" password:@"PASSWORD" persistence:NSURLCredentialPersistenceForSession]; NSLog(@"credential created"); [[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge]; NSLog(@"responded to authentication challenge"); } else { NSLog(@"previous authentication failure"); } } - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { ... } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { ... } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { ... } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { ... }


Si está utilizando GTMHTTPFetcher para su conexión, la autenticación básica es bastante fácil también. Simplemente debe proporcionar la credencial al buscador antes de comenzar la búsqueda.

NSString * urlString = @"http://www.testurl.com/"; NSURL * url = [NSURL URLWithString:urlString]; NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url]; NSURLCredential * credential = [NSURLCredential credentialWithUser:@"username" password:@"password" persistence:NSURLCredentialPersistenceForSession]; GTMHTTPFetcher * gFetcher = [GTMHTTPFetcher fetcherWithRequest:request]; gFetcher.credential = credential; [gFetcher beginFetchWithDelegate:self didFinishSelector:@selector(fetchCompleted:withData:andError:)];


Si no desea importar todo MGTwitterEngine y no está haciendo una solicitud asíncrona, puede utilizar http://www.chrisumbel.com/article/basic_authentication_iphone_cocoa_touch

Para base64 codifique el nombre de usuario y la contraseña, así que reemplace

NSString *authValue = [NSString stringWithFormat:@"Basic %@", [authData base64EncodingWithLineLength:80]];

con

NSString *encodedLoginData = [Base64 encode:[loginString dataUsingEncoding:NSUTF8StringEncoding]];

después

Deberás incluir el siguiente archivo

static char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @implementation Base64 +(NSString *)encode:(NSData *)plainText { int encodedLength = (((([plainText length] % 3) + [plainText length]) / 3) * 4) + 1; unsigned char *outputBuffer = malloc(encodedLength); unsigned char *inputBuffer = (unsigned char *)[plainText bytes]; NSInteger i; NSInteger j = 0; int remain; for(i = 0; i < [plainText length]; i += 3) { remain = [plainText length] - i; outputBuffer[j++] = alphabet[(inputBuffer[i] & 0xFC) >> 2]; outputBuffer[j++] = alphabet[((inputBuffer[i] & 0x03) << 4) | ((remain > 1) ? ((inputBuffer[i + 1] & 0xF0) >> 4): 0)]; if(remain > 1) outputBuffer[j++] = alphabet[((inputBuffer[i + 1] & 0x0F) << 2) | ((remain > 2) ? ((inputBuffer[i + 2] & 0xC0) >> 6) : 0)]; else outputBuffer[j++] = ''=''; if(remain > 2) outputBuffer[j++] = alphabet[inputBuffer[i + 2] & 0x3F]; else outputBuffer[j++] = ''=''; } outputBuffer[j] = 0; NSString *result = [NSString stringWithCString:outputBuffer length:strlen(outputBuffer)]; free(outputBuffer); return result; } @end