iPhone: NSHTTPCookie не сохраняется через перезагрузки приложений

В моем приложении для iPhone я хочу иметь возможность повторно использовать тот же сеанс на стороне сервера, когда мое приложение перезагрузится. Сеанс на сервере идентифицируется cookie, который отправляется по каждому запросу. Когда я перезапущу приложение, этот файл cookie исчез, и я больше не могу использовать тот же сеанс.

Что я заметил, когда я использовал NSHTTPCookieStorage для поиска cookie, который я получил с сервера, является то, что [cookie isSessionOnly] возвращает YES . У меня создается впечатление, что именно поэтому куки-файлы не сохраняются в перезагрузках моего приложения. Что мне нужно сделать, чтобы сделать мой cookie НЕ сеансом? Какие заголовки HTTP мне нужно отправить с сервера?

Вы можете сохранить файл cookie, сохранив словарь свойств, а затем восстановив его в качестве нового файла cookie перед тем, как перейти к повторному подключению.

Сохранить:

 NSArray* allCookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[NSURL URLWithString:URL]]; for (NSHTTPCookie *cookie in allCookies) { if ([cookie.name isEqualToString:MY_COOKIE]) { NSMutableDictionary* cookieDictionary = [NSMutableDictionary dictionaryWithDictionary:[[NSUserDefaults standardUserDefaults] dictionaryForKey:PREF_KEY]]; [cookieDictionary setValue:cookie.properties forKey:URL]; [[NSUserDefaults standardUserDefaults] setObject:cookieDictionary forKey:PREF_KEY]; } } 

Нагрузка:

 NSDictionary* cookieDictionary = [[NSUserDefaults standardUserDefaults] dictionaryForKey:PREF_KEY]; NSDictionary* cookieProperties = [cookieDictionary valueForKey:URL]; if (cookieProperties != nil) { NSHTTPCookie* cookie = [NSHTTPCookie cookieWithProperties:cookieProperties]; NSArray* cookieArray = [NSArray arrayWithObject:cookie]; [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:cookieArray forURL:[NSURL URLWithString:URL] mainDocumentURL:nil]; } 

У меня есть ответ на @ TomIrving, и я здесь прорабатываю, потому что многие пользователи не увидят очень важный комментарий, в котором он говорит:

«Вам нужно установить дату истечения срока, иначе cookie будет считаться сессией».

В основном, файл cookie будет удален, когда вы закроете свое приложение, если в будущем cookie имеет дату истечения срока действия.

Вам не нужно сохранять и восстанавливать cookies и из NSUserDefaults если у вас есть контроль над сервером, и можете попросить его установить заголовок «Expires» на что-то в будущем. Если у вас нет контроля над сервером или вы не хотите переопределять поведение своего сервера, вы можете «обмануть» ваше приложение, изменив expiresDate из него:

  • Получите файл cookie, который вы хотите изменить из [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]
  • Скопируйте его свойства в новый NSMutableDictionary , изменив значение "Expires" на дату в будущем.
  • Создайте новый файл cookie из нового NSMutableDictionary используя: [NSHTTPCookie.cookieWithProperties:]
  • Сохраните созданный файл cookie с помощью [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie newCookie]

При повторном открытии приложения вы заметите, что файл cookie не был удален.

Куки-файлы только для сеанса истекают по своей природе. Вы можете сохранить их вручную в Keychain, если вы действительно этого хотите. Я предпочитаю Keychain сохранять в UserDefaults или архивировать, потому что cookies лучше защищаются, как и пароль пользователя.

К сожалению, сохранение куки-файлов только для сеансов не очень полезно, приведенный ниже код является лишь иллюстрацией того, как хранить куки-файлы, но не может заставить сервер принимать такие cookies любым способом (если только вы не можете контролировать сервер).

Swift 2.2

 // Saving into Keychain if let cookies = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies { let cookiesData: NSData = NSKeyedArchiver.archivedDataWithRootObject(cookies) let userAccount = "some unique string to identify the item in Keychain, in my case I use username" let domain = "some other string you can use in combination with userAccount to identify the item" let keychainQuery: [NSString: NSObject] = [ kSecClass: kSecClassGenericPassword, kSecAttrAccount: userAccount + "cookies", kSecAttrService: domain, kSecValueData: cookiesData] SecItemDelete(keychainQuery as CFDictionaryRef) //Trying to delete the item from Keychaing just in case it already exists there let status: OSStatus = SecItemAdd(keychainQuery as CFDictionaryRef, nil) if (status == errSecSuccess) { print("Cookies succesfully saved into Keychain") } } // Getting from Keychain let userAccount = "some unique string to identify the item in Keychain, in my case I use username" let domain = "some other string you can use in combination with userAccount to identify the item" let keychainQueryForCookies: [NSString: NSObject] = [ kSecClass: kSecClassGenericPassword, kSecAttrService: domain, // we use JIRA URL as service string for Keychain kSecAttrAccount: userAccount + "cookies", kSecReturnData: kCFBooleanTrue, kSecMatchLimit: kSecMatchLimitOne] var rawResultForCookies: AnyObject? let status: OSStatus = SecItemCopyMatching(keychainQueryForCookies, &rawResultForCookies) if (status == errSecSuccess) { let retrievedData = rawResultForCookies as? NSData if let unwrappedData = retrievedData { if let cookies = NSKeyedUnarchiver.unarchiveObjectWithData(unwrappedData) as? [NSHTTPCookie] { for aCookie in cookies { NSHTTPCookieStorage.sharedHTTPCookieStorage().setCookie(aCookie) } } } } 

Я считаю, что до сервера нужно решить, является ли cookie только сеансом, вы ничего не можете с этим поделать.

Быстрый способ

Хранить:

 static func storeCookies() { let cookiesStorage = NSHTTPCookieStorage.sharedHTTPCookieStorage() let userDefaults = NSUserDefaults.standardUserDefaults() let serverBaseUrl = "http://yourserverurl.com" var cookieDict = [String : AnyObject]() for cookie in cookiesStorage.cookiesForURL(NSURL(string: serverBaseUrl)!)! { cookieDict[cookie.name] = cookie.properties } userDefaults.setObject(cookieDict, forKey: cookiesKey) } 

Восстановить:

 static func restoreCookies() { let cookiesStorage = NSHTTPCookieStorage.sharedHTTPCookieStorage() let userDefaults = NSUserDefaults.standardUserDefaults() if let cookieDictionary = userDefaults.dictionaryForKey(cookiesKey) { for (cookieName, cookieProperties) in cookieDictionary { if let cookie = NSHTTPCookie(properties: cookieProperties as! [String : AnyObject] ) { cookiesStorage.setCookie(cookie) } } } } 

SWIFT 3

СПАСТИ:

 if let httpResponse = response as? HTTPURLResponse, let fields = httpResponse.allHeaderFields as? [String : String] { let cookies = HTTPCookie.cookies(withResponseHeaderFields: fields, for: response.url!) HTTPCookieStorage.shared.setCookies(cookies, for: response.url!, mainDocumentURL: nil) for cookie in cookies { if cookie.name == cookieName{ if cookieName == Constants.WS.COOKIES.COOKIE_SMS { UserDefaults.standard.set(NSKeyedArchiver.archivedData(withRootObject: cookie), forKey: Constants.SHARED_DEFAULT.COOKIE_SMS) UserDefaults.standard.synchronize() } return cookie.value } } } 

ПОЛУЧИТЬ:

 let cookie: HTTPCookie = NSKeyedUnarchiver.unarchiveObject(with: UserDefaults.standard.object(forKey: Constants.SHARED_DEFAULT.COOKIE_SMS) as! Data) as! HTTPCookie HTTPCookieStorage.shared.setCookie(cookie) 
  • Использовать метод didSelectRowAtIndexPath или prepareForSegue для UITableView?
  • Преобразование & amp; to & in Objective-C
  • Устройство iPhone против симулятора iPhone
  • objective «База» против «Активный» и «Развертывание»
  • AVFoundation, как отключить звук затвора при захватеStillImageAsynchronouslyFromConnection?
  • Предупреждение о разрешении местоположения на iPhone с помощью PhoneGap
  • UIScrollView не прокрутка
  • Как программно воспринимать переключатель отключения звука iPhone?
  • Преобразование NSDate в NSString
  • Собственное использование приложения делегата приложения iPhone
  • Core-Data iPhone: не удалось найти NSManagedObjectModel
  • Давайте будем гением компьютера.