NSURLConnection and basic HTTP authentication in iOS

I need to call the initial GET HTTP request using Basic Authentication . This will be the first time a request is sent to the server, and I already have username & password , so there is no need to call from the server for authorization.

First question:

  • Do I need to install NSURLConnection as synchronous with Basic Auth? According to the answer to this post , it seems that you cannot perform Basic Auth if you choose an asynchronous route.

  • Does anyone know any sample code that illustrates Basic Auth on a GET request without having to answer the call? Apple's documentation shows an example, but only after the server issues a request for a request to the client.

I’m kind of the new network part of the SDK, and I'm not sure which of the other classes I should use to get this to work. (I see the NSURLCredential class, but it seems that it is only used with the NSURLAuthenticationChallenge after the client has requested an authorized resource from the server).

+78
ios objective-c iphone nsurlconnection
Dec 29 '09 at 7:06
source share
7 answers

I use an asynchronous connection with MGTwitterEngine and set the authorization to NSMutableURLRequest ( theRequest ) so

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

I do not believe that this method requires going through a request loop, but I could be wrong

+127
Dec 29 '09 at 13:08
source

Even the answer to the question, I want to present a solution that does not require external libraries, I found in another thread:

 // 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 { ... } 
+79
Jul 25 2018-11-11T00:
source

Here is a detailed answer without a third party:

Please check here:

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

Please let me know your feedback on this.

thank

+9
Jan 28 '15 at 7:34
source

If you do not want to import the entire MGTwitterEngine, and you are not performing an asynchronous request, then you can use http://www.chrisumbel.com/article/basic_authentication_iphone_cocoa_touch

To base64 encode username and password so replace

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

from

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

after

you will need to include the following file

 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 
+7
Feb 27 '12 at 16:20
source

Since NSData :: dataUsingEncoding is deprecated (ios 7.0), you can use this solution:

 // 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"]; 
+2
Sep 04 '16 at 7:29
source

If you use GTMHTTPFetcher for your connection, basic authentication is also quite simple. You just need to provide the credentials for the recipient before starting the fetch.

 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:)]; 
+1
Mar 05 '12 at 4:10
source

Can you tell me what is the reason for limiting the length of the coding line to 80 in your code example? I thought that the HTTP headers have a maximum length of about 4k (or maybe some servers do not take longer). - Justin Galzic Justin Galzic

This is not a limit to 80, it is an option of the base64EncodingWithLineLength method in NSData + Base64.h / m, where you can split the encoded string into several lines, which is useful for another application, for example, for transmitting nntp. I believe that 80 was chosen by the author of the twitter engine as a length large enough to fit most user / password-protected results to a single line.

0
Apr 21 '10 at 21:09
source



All Articles