Мне нужно вызвать начальную букву GET HTTP request
с помощью Basic Authentication
. Это будет первый раз, когда запрос будет отправлен на сервер, и у меня уже есть запрос, username & password
поэтому нет необходимости в запросе с сервера для авторизации.
Первый вопрос:
Должен ли
NSURLConnection
быть установлен синхронный режим для базовой аутентификации? Согласно ответу на этот пост , кажется, что вы не сможете выполнить базовую аутентификацию, если выберете асинхронный маршрут.Кто-нибудь знает какой-либо пример кода, который иллюстрирует базовую аутентификацию
GET request
без необходимости ответа на запрос? В документации Apple показан пример, но только после того, как сервер отправил клиенту запрос вызова.
Я как бы новичок в сетевой части SDK, и я не уверен, какой из других классов мне следует использовать, чтобы это работало. (Я вижу NSURLCredential
класс, но кажется, что он используется только NSURLAuthenticationChallenge
после того, как клиент запросил авторизованный ресурс с сервера).
источник
[authData base64EncodedString]
) добавьте файлы NSData + Base64.h и .m от Мэтта Галлахера в свой XCode-Project ( параметры кодирования Base64 на Mac и iPhone ).base64Encoding
устарел с iOS 7.0 и OS X 10.9. Я использую[authData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]
вместо этого. Также доступны `NSDataBase64Encoding64CharacterLineLength` илиNSDataBase64Encoding76CharacterLineLength
Даже если на вопрос дан ответ, я хочу представить решение, не требующее внешних библиотек, которое я нашел в другом потоке:
// 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 { ... }
источник
Вот подробный ответ без участия третьих лиц:
Пожалуйста, проверьте здесь:
//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]; } }]
Пожалуйста, дайте мне знать ваш отзыв по этому поводу.
Благодарность
источник
- (NSString *)base64Encoding NS_DEPRECATED(10_6, 10_9, 4_0, 7_0);
использовать: вместо этого лучше использовать категорию NSDataBase64Encoding.Если вы не хотите импортировать весь MGTwitterEngine и не выполняете асинхронный запрос, вы можете использовать http://www.chrisumbel.com/article/basic_authentication_iphone_cocoa_touch
Чтобы base64 закодировал имя пользователя и пароль, замените
NSString *authValue = [NSString stringWithFormat:@"Basic %@", [authData base64EncodingWithLineLength:80]];
с участием
NSString *encodedLoginData = [Base64 encode:[loginString dataUsingEncoding:NSUTF8StringEncoding]];
после
вам нужно будет включить следующий файл
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
источник
Поскольку NSData :: dataUsingEncoding устарел (ios 7.0), вы можете использовать это решение:
// 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"];
источник
Если вы используете GTMHTTPFetcher для своего соединения, базовая аутентификация также довольно проста. Вам просто нужно предоставить учетные данные для сборщика перед началом выборки.
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:)];
источник
Это не ограничение до 80, это опция метода base64EncodingWithLineLength в NSData + Base64.h / m, где вы можете разделить закодированную строку на несколько строк, что полезно для других приложений, таких как передача nntp. Я считаю, что 80 выбрано автором движка твиттера как длина, достаточная для размещения большинства результатов, закодированных пользователем / паролем, в одной строке.
источник
Вы можете использовать AFNetworking (это открытый исходный код), вот код, который работал у меня. Этот код отправляет файл с базовой аутентификацией. Просто измените URL, адрес электронной почты и пароль.
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];
источник