Muszę wywołać inicjał GET HTTP request
w Basicu Authentication
. To byłby pierwszy raz, gdy żądanie jest wysyłane do serwera, a ja już je mam, username & password
więc nie ma potrzeby wezwania serwera do autoryzacji.
Pierwsze pytanie:
Czy
NSURLConnection
musi być ustawione jako synchroniczne, aby wykonać uwierzytelnianie podstawowe? Zgodnie z odpowiedzią w tym poście wydaje się, że nie możesz wykonać podstawowego uwierzytelnienia, jeśli zdecydujesz się na trasę asynchroniczną.Czy ktoś zna jakiś przykładowy kod, który ilustruje uwierzytelnianie podstawowe
GET request
bez potrzeby odpowiedzi na wezwanie? Dokumentacja firmy Apple pokazuje przykład, ale dopiero po wysłaniu przez serwer żądania wezwania do klienta.
Jestem trochę nowy w sieciowej części SDK i nie jestem pewien, której z innych klas powinienem użyć, aby to działało. (Widzę tę NSURLCredential
klasę, ale wygląda na to, że jest używana tylko wtedy, NSURLAuthenticationChallenge
gdy klient zażąda autoryzowanego zasobu z serwera).
źródło
[authData base64EncodedString]
), dodaj pliki NSData + Base64.h i .m od Matta Gallaghera do swojego XCode-Project ( opcje kodowania Base64 na komputerach Mac i iPhone ).base64Encoding
jest przestarzały od wersji iOS 7.0 i OS X 10.9. Używam[authData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]
zamiast tego. Dostępne są również `NSDataBase64Encoding64CharacterLineLength` lubNSDataBase64Encoding76CharacterLineLength
Nawet na pytanie mam odpowiedź, chcę przedstawić rozwiązanie, które nie wymaga zewnętrznych bibliotek, znalazłem w innym wątku:
// 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 { ... }
źródło
Oto szczegółowa odpowiedź bez udziału strony trzeciej:
Proszę sprawdzić tutaj:
//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]; } }]
Uprzejmie daj mi znać swoją opinię na ten temat.
Dzięki
źródło
- (NSString *)base64Encoding NS_DEPRECATED(10_6, 10_9, 4_0, 7_0);
lepiej jest zamiast tego użyć kategorii NSDataBase64Encoding.Jeśli nie chcesz importować całego MGTwitterEngine i nie wykonujesz asynchronicznego żądania Następnie możesz użyć http://www.chrisumbel.com/article/basic_authentication_iphone_cocoa_touch
Aby zakodować base64 nazwę użytkownika i hasło, zamień
NSString *authValue = [NSString stringWithFormat:@"Basic %@", [authData base64EncodingWithLineLength:80]];
z
NSString *encodedLoginData = [Base64 encode:[loginString dataUsingEncoding:NSUTF8StringEncoding]];
po
będziesz musiał dołączyć następujący plik
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
źródło
Ponieważ NSData :: dataUsingEncoding jest przestarzałe (ios 7.0), możesz użyć tego rozwiązania:
// 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"];
źródło
Jeśli używasz GTMHTTPFetcher do połączenia, podstawowe uwierzytelnianie jest również dość łatwe. Wystarczy podać dane uwierzytelniające do modułu pobierania przed rozpoczęciem pobierania.
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:)];
źródło
Nie ogranicza się do 80, jest to opcja metody base64EncodingWithLineLength w NSData + Base64.h / m, w której można podzielić zakodowany ciąg na wiele linii, co jest przydatne w innych aplikacjach, takich jak transmisja nntp. Uważam, że autor silnika Twittera wybrał 80 jako wystarczająco dużą długość, aby pomieścić większość wyników zakodowanych przez użytkownika / hasło w jednej linii.
źródło
Możesz użyć AFNetworking (jest to opensource), oto kod, który działał dla mnie. Ten kod wysyła plik z podstawowym uwierzytelnieniem. Po prostu zmień adres URL, adres e-mail i hasło.
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];
źródło