AFNetworking и Cookies

Я использую AFNetworking в качестве сетевого уровня для своего iPhone-приложения, которое подключается к серверу Rails, который использует Devise для аутентификации. Если я вхожу в систему (с вызовом POST), предоставляя имя пользователя/пароль, то после этого любой GET, который я выполняю, в порядке.

Если я закрою приложение (а не только фон), то все мои запросы GET завершатся неудачно, потому что я предполагаю, что они не аутентифицированы.

Поэтому я предполагаю, что файлы cookie хранятся где-то; есть ли способ сохранить их в NSUserDefaults или где-то в этом роде, чтобы избежать регистрации во все время?

Ответ 1

Файлы cookie действительно автоматически сохраняются в течение всего срока службы вашего приложения для любых последующих запросов на конкретном сервере. Хорошей стратегией было бы сохранить имя пользователя и пароль в цепочке ключей или в NSUserDefaults следующим образом:

// Setting
[[NSUserDefaults standardDefaults] setObject:username forKey:@"username"];
[[NSUserDefaults standardDefaults] synchronize];

// Getting
NSString *username = [[NSUserDefaults standardDefaults] objectForKey:@"username"];

Вы можете использовать это в сочетании с AFHTTPClient для отправки ваших учетных данных вместе с каждым запросом в заголовке HTTP Authorization.

Ответ 2

Вам не нужно беспокоиться о NSUserDefaults или любой оболочке связки ключей, если вы используете NSURLCredential. Действительно, NSURLCredential гораздо проще использовать, поскольку он позволяет хранить как имя пользователя, так и пароль в цепочке ключей в двух строках кода.

Ваш код будет примерно таким, как только пользователь выполнит вход:

NSURLCredential *credential;

credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
[[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:self.loginProtectionSpace];

Затем при каждом запуске приложения вы можете проверить, был ли ваш пользователь уже зарегистрирован, выполнив поиск всех учетных данных, чтобы автоматически регистрировать пользователя (если необходимо):

NSURLCredential *credential;
NSDictionary *credentials;

credentials = [[NSURLCredentialStorage sharedCredentialStorage] credentialsForProtectionSpace:self.loginProtectionSpace];
credential = [credentials.objectEnumerator nextObject];
NSLog(@"User %@ already connected with password %@", credential.user, credential.password);

Вам также необходимо очистить учетные данные, когда пользователь хочет выйти из системы:

NSURLCredential *credential;
NSDictionary *credentials;

credentials = [[NSURLCredentialStorage sharedCredentialStorage] credentialsForProtectionSpace:self.loginProtectionSpace];
credential = [credentials.objectEnumerator nextObject];
[[NSURLCredentialStorage sharedCredentialStorage] removeCredential:credential forProtectionSpace:self.loginProtectionSpace];

loginProtectionSpace создается один раз для всех. Пожалуйста, обратите внимание, что этот пример кода предполагает, что в этом пространстве есть только один учетный код, что обычно бывает, если вы не управляете несколькими учетными записями.

Вот пример того, как вы создадите NSURLProtectionSpace:

NSURL *url = [NSURL URLWithString:@"http://www.example.com"];
self.loginProtectionSpace = [[NSURLProtectionSpace alloc] initWithHost:url.host
                                                                  port:[url.port integerValue]
                                                              protocol:url.scheme
                                                                 realm:nil
                                                  authenticationMethod:NSURLAuthenticationMethodHTTPDigest];