Аутентификация с помощью NSURLConnection sendAsynchronousRequest с обработчиком завершения
Как правило, мне нравится просто "стрелять и забывать" с помощью метода класса NSASL sendAsynchronousRequest, используя блок обработчика завершения, но кажется, что это может быть не вариант, когда требуется аутентификация.
При использовании запроса стиля обработчика завершения следующим образом:
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.mysite.com/"]]
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
//Do Stuff
}];
Каков правильный способ проверки подлинности? Нужно ли мне выделять и инициализировать NSURLConnection и устанавливать делегат вместо того, чтобы использовать этот стиль метода класса? Я думаю, что я понимаю, как правильно аутентифицировать функцию делегата, но я пытаюсь выяснить, могу ли я включить это в блок завершенияHandler или если есть лучший способ сделать это.
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge previousFailureCount] > 0) {
NSLog(@"Authentication Failure");
[connection cancel];
}
else
{
NSURLCredential *credential = [NSURLCredential credentialWithUser:self.username
password:self.password
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
}
Ответы
Ответ 1
Я думаю, метод completeHandler для базовых запросов. Возможно, вы могли бы использовать AFNetworking, поскольку я использую это с блочными методами и аутентификацией.
ИЗМЕНИТЬ....
Вы пытались добавить заголовок аутентификации в NSURLRequest?
Создайте NSMutableURLRequest:
NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.example.com/"]];
И добавьте заголовок для проверки подлинности следующим образом:
NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", userName, password];
NSString *authValue = [NSString stringWithFormat:@"Basic %@", AFBase64EncodedStringFromString(basicAuthCredentials)];
[urlRequest setValue:authValue forHTTPHeaderField:@"Authorization"];
Функция AFBase64EncodedStringFromString такова:
static NSString * AFBase64EncodedStringFromString(NSString *string) {
NSData *data = [NSData dataWithBytes:[string UTF8String] length:[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
NSUInteger length = [data length];
NSMutableData *mutableData = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t *input = (uint8_t *)[data bytes];
uint8_t *output = (uint8_t *)[mutableData mutableBytes];
for (NSUInteger i = 0; i < length; i += 3) {
NSUInteger value = 0;
for (NSUInteger j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) {
value |= (0xFF & input[j]);
}
}
static uint8_t const kAFBase64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
NSUInteger idx = (i / 3) * 4;
output[idx + 0] = kAFBase64EncodingTable[(value >> 18) & 0x3F];
output[idx + 1] = kAFBase64EncodingTable[(value >> 12) & 0x3F];
output[idx + 2] = (i + 1) < length ? kAFBase64EncodingTable[(value >> 6) & 0x3F] : '=';
output[idx + 3] = (i + 2) < length ? kAFBase64EncodingTable[(value >> 0) & 0x3F] : '=';
}
return [[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding];
}
Затем вызовите функцию, которую вы вызывали раньше, но используя новый NSURLRequest:
[NSURLConnection sendAsynchronousRequest:urlRequest
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
}];
Ответ 2
Хотя проблема сейчас решена, я хочу добавить решение, которое не требует сторонних библиотек:
//HTTP Authentication
NSString *authStr = [NSString stringWithFormat:@"%@:%@", @"Username", @"Password"]];
NSData *authData = [authStr dataUsingEncoding:NSASCIIStringEncoding];
NSString *authValue = [authData base64Encoding];
//Set up Request:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]init];
[request setURL:[NSURL URLWithString:url]];
//...
// Pack in the user credentials
[request setValue:[NSString stringWithFormat:@"Basic %@",authValue] forHTTPHeaderField:@"Authorization"];
// Send the asynchronous request as usual
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *responseCode, NSData *responseData, NSError *error) {
// Do stuff..
}
Ответ 3
NSURLConnection is deprecated in iOS 9, try this code which is from LazyTableImages example from here [https://developer.apple.com/library/ios/samplecode/LazyTableImages/Introduction/Intro.html][1]
@property (nonatomic, strong) NSURLSessionDataTask *sessionTask;
//somwere in your code
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
initWithURL:[NSURL URLWithString:self.postLink] ];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:NO];
[request setTimeoutInterval:60];
[request setHTTPMethod:@"POST"];
[request addValue:[[NSUserDefaults standardUserDefaults] objectForKey:@"token"]
forHTTPHeaderField:@"ACCESSTOKEN"];
self.sessionTask = [[NSURLSession sharedSession] dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
//do completion staff here
}];