Necesito invocar una inicial GET HTTP request
con Basic Authentication
. Esta sería la primera vez que se envía la solicitud al servidor y ya la tengo, username & password
por lo que no es necesario que el servidor impugne la autorización.
Primera pregunta:
¿
NSURLConnection
Tiene que estar configurado como síncrono para realizar la autenticación básica? Según la respuesta de esta publicación , parece que no puede realizar la autenticación básica si opta por la ruta asíncrona.¿Alguien sabe de algún código de muestra que ilustre la autenticación básica en un
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 esto funcione. (Veo la NSURLCredential
clase, pero parece que se usa solo NSURLAuthenticationChallenge
después de que el cliente haya solicitado un recurso autorizado del servidor).
fuente
[authData base64EncodedString]
), agregue el archivo NSData + Base64.hy .m de Matt Gallagher a su XCode-Project ( opciones de codificación Base64 en Mac y iPhone ).base64Encoding
está obsoleto desde iOS 7.0 y OS X 10.9. Yo uso[authData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]
en su lugar. También están disponibles `NSDataBase64Encoding64CharacterLineLength` oNSDataBase64Encoding76CharacterLineLength
Incluso la pregunta está respondida, quiero presentar la solución, que no requiere bibliotecas externas, 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 { ... }
fuente
Aquí hay una respuesta detallada sin terceros involucrados:
Por favor marque 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 déjeme saber sus comentarios al respecto.
Gracias
fuente
- (NSString *)base64Encoding NS_DEPRECATED(10_6, 10_9, 4_0, 7_0);
mejor usar la categoría NSDataBase64Encoding en su lugar.Si no desea importar todo MGTwitterEngine y no está realizando una solicitud asincrónica, puede usar http://www.chrisumbel.com/article/basic_authentication_iphone_cocoa_touch
Para codificar en base64 el nombre de usuario y la contraseña, 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
fuente
Dado que NSData :: dataUsingEncoding está obsoleto (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"];
fuente
Si está utilizando GTMHTTPFetcher para su conexión, la autenticación básica también es bastante fácil. 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:)];
fuente
No se limita a 80, es una opción del método base64EncodingWithLineLength en NSData + Base64.h / m, donde puede dividir su cadena codificada en varias líneas, lo cual es útil para otras aplicaciones, como la transmisión nntp. Creo que 80 es elegido por el autor del motor de Twitter para tener una longitud lo suficientemente grande como para acomodar la mayoría de los resultados codificados por usuario / contraseña en una línea.
fuente
Puede usar AFNetworking (es de código abierto), aquí está el código que funcionó para mí. Este código envía un archivo con autenticación básica. Simplemente cambie la URL, el correo electrónico y la contraseña.
NSString *serverUrl = [NSString stringWithFormat:@"http://www.yoursite.com/uploadlink", profile.host]; NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:serverUrl parameters:nil error:nil]; NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; // Forming string with credentials 'myusername:mypassword' NSString *authStr = [NSString stringWithFormat:@"%@:%@", email, emailPassword]; // 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"]; manager.responseSerializer = [AFHTTPResponseSerializer serializer]; NSURL *filePath = [NSURL fileURLWithPath:[url path]]; NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:^(NSProgress * _Nonnull uploadProgress) { // This is not called back on the main queue. // You are responsible for dispatching to the main queue for UI updates dispatch_async(dispatch_get_main_queue(), ^{ //Update the progress view LLog(@"progres increase... %@ , fraction: %f", uploadProgress.debugDescription, uploadProgress.fractionCompleted); }); } completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { if (error) { NSLog(@"Error: %@", error); } else { NSLog(@"Success: %@ %@", response, responseObject); } }]; [uploadTask resume];
fuente