iPhone:NSHTTPCookie未在应用重启期间保存

Tom*_*ren 30 iphone cookies

在我的iPhone应用程序中,我希望能够在我的应用程序重新启动时重用相同的服务器端会话.服务器上的会话由cookie标识,cookie在每个请求上发送.当我重新启动应用程序时,该cookie已经消失,我不能再使用相同的会话了.

当我用它NSHTTPCookieStorage查找从服务器获得的cookie 时,我注意到的是[cookie isSessionOnly]返回YES.我得到的印象是,这就是为什么不会在重新启动应用时保存Cookie的原因.我需要做什么才能使我的cookie不仅仅是会话?我必须从服务器发送哪些HTTP标头?

Mik*_*atz 44

您可以通过保存其属性字典来保存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];
    }
 }
Run Code Online (Sandbox Code Playgroud)

加载:

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];
}
Run Code Online (Sandbox Code Playgroud)

  • 你需要同步 nsuserdefaults 吗? (2认同)

Abd*_*bdo 23

我赞成了@ TomIrving的回答并在此详细阐述,因为许多用户不会看到他说的非常重要的评论:

"你需要设置一个到期日期,否则假设cookie只是会话."

基本上,当您关闭应用程序时,cookie将被删除,除非cookie将来有一个到期日期.

NSUserDefaults如果您可以控制服务器,则无需在cookie中存储和恢复cookie,并且可以要求它在将来将"Expires"标题设置为某些内容.如果您无法控制服务器或者不希望覆盖服务器的行为,则可以通过更改其中的内容来"欺骗"您的应用expiresDate:

当您重新打开应用程序时,您会注意到cookie尚未删除.

  • 从服务器端安全方法来看,这应该是公认的答案. (2认同)

Vit*_*lii 5

仅会话的cookie会因其性质而过期。如果确实需要,可以将它们手动存储在钥匙串中。我更喜欢钥匙串而不是保存在UserDefaults或归档中,因为最好像用户密码一样保护cookie。

不幸的是,保存仅会话的cookie并不是很有帮助,下面的代码只是说明如何存储cookie,但不能强制服务器以任何方式接受此类cookie(除非您可以控制服务器)。

斯威夫特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)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)