2012-05-21 54 views
3

我發送http請求與session-cookie存儲在設備端。問題是我想在應用程序終止時堅持它。但似乎我的應用程序的所有cookie都被刪除了。我嘗試了模擬器和設備,他們得到了相同的行爲。iOS應用程序的Cookie在終止時被清除。如何防止這一點,或堅持這個cookie?

是否有任何iOS方式來防止此cookie被刪除?如果沒有,我如何將它保存到磁盤並恢復它?

我打算將這個cookie保存在iOS鑰匙串中以保證安全。我認爲所有NSHTTPCookie屬性都可以安全地轉換爲NSString。所以我目前的想法是從轉換NSHTTPCookie - > NSDictionary - >字符串 - >保存在鑰匙串,並返回使用獲取原始cookie。問題是我不想通過轉換NSDictionary - >字符串和解析字符串 - > NSDictionary的麻煩。

+0

您可以自行保存併發送餅乾。 –

+0

是的,但iOS是否提供這種機制? – Hlung

+0

有點兒。如果你有一個NSHTTPURLResponse,你可以通過NSHTTPCookie的cookiesWithResponseHeaderFields:forURL:方法得到NSArray的NSHTTPCookies。然後發送它們,你只需要自己創建Cookie:頭。我會在答案中發佈更多細節。 –

回答

1

=====摘要=====

好吧,我要創建另一個答案只是總結可能的方式來堅持一個NSDictionary中(即不當然包含對象!)。

最簡單的方法是使用NSDictionary的writeToFile:方法。這將生成一個plist文件。 (也可在NSArray中找到)如果您擔心安全問題,請將數組加密到NSData對象並寫入。

另一種方式,不是最快的方法,是使用工具將NSDictionary轉換爲字符串格式,如JSON或XML。您可以將此字符串保存在iOS鑰匙串中,並在以後輕鬆檢索。 (SFHFKeychainUtils是一個偉大的幫助鑰匙鏈的東西)。使用鑰匙串的好處是它會自動加密。

1

假設你有一個NSHTTPURLResponse,你可以得到的Cookie的數組,像這樣:

NSDictionary * headers = [(NSHTTPURLResponse *)response allHeaderFields]; 
NSArray * cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:headers forURL:response.URL]; 

哪裏response是NSHTTPURLResponse。

你會得到NSURLResponses在NSURLConnectionDelegate

- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse; 
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response; 

NSHTTPCookie的這2種方法有properties屬性,它返回一個NSDictionary,這樣你就可以保存它們。 然後可以使用-initWithProperties:

使用相同字典創建它們要發送它們,您需要爲NSURLRequest的Cookie標頭創建自己的字符串。 喜歡的東西:

NSMutableString * cookieString = [[NSMutableString alloc] init]; 
for (NSHTTPCookie * cookie in myLoadedCookies){ 
    [cookieString appendFormat:@"%@=%@; ", cookie.name, cookie.value]; 
} 
[request setValue:cookieString forHTTPHeaderField:@"Cookie"]; 
[cookieString release]; 

requestNSMutableURLRequest

你也應該確保停止的iOS管理cookie本身:

[request setHTTPShouldHandleCookies:NO]; 
+0

我使用Restkit來發送和接收請求,所以我不直接處理NSURLRequest。我得到這個cookie的方式是'[NSHTTPCookieStorage sharedHTTPCookieStorage] .cookies',在我的情況下,它將和你的代碼一樣工作。問題是如何將NSHTTPCookie保存到磁盤。我找到了比遍歷每個NSDictionary條目更好的方法,並生成一個可以保存到iOS鑰匙串(用於安全性)的長字符串,然後再次將該字符串解析爲NSDictionary以恢復該cookie。我不想通過解析麻煩:( – Hlung

+1

如果你可以保存一個NSDrayarys的NSArray沒有意義解析NSArray有一個writeToFile方法和一個你可以使用的initWithContentsOfFile如果你擔心安全性,數組寫入一個NSData對象並編寫它 –

+0

噢,謝謝,我不知道這些集合類有一個'writeToFile:'方法。 – Hlung

2

發現這樣做的一個很好的清潔方式。訣竅是使用JSONKit(附帶RestKit)來使用JSON格式在NSString和NSDictionary之間進行轉換。在這裏,我使用SFHFKeychainUtils來幫助我使用鑰匙鏈。這樣你就不必擔心cookie中的每個屬性和所有的轉換工作。 :)

#import "RestKit/JSONKit.h" 

#define WSC_serviceName @"WSC_serviceName" 
#define WSC_username @"WSC_username" 
#define WSC_cookieName @"_your_cookie_name" // name of the session cookie 

- (void)saveSessionCookieToKeyChain { 
    for (NSHTTPCookie *c in [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies) { 
     if ([c.name isEqualToString:WSC_cookieName]) { 
      NSString *cookieString = [c.properties JSONString]; 
      NSLog(@"cookieString: %@",cookieString); 
      NSError *saveError = nil; 
      [SFHFKeychainUtils storeUsername:WSC_username 
           andPassword:cookieString 
           forServiceName:WSC_serviceName 
           updateExisting:YES error:&saveError]; 
     } 
    } 
} 

- (BOOL)readsSessionCookieFromKeyChain { 
    NSError *readError = nil; 
    NSString *jsonString = [SFHFKeychainUtils getPasswordForUsername:WSC_username 
                 andServiceName:WSC_serviceName 
                   error:&readError]; 
    if (!jsonString) return NO; 
    NSData* jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; // be sure that data is in UTF8 or it won't work 
    JSONDecoder* decoder = [[JSONDecoder alloc] initWithParseOptions:JKParseOptionNone]; 
    NSDictionary* jsonDict = (NSDictionary*)[decoder objectWithData:jsonData]; 
    NSLog(@"jsonDict: %@",jsonDict); 

    NSHTTPCookie *cookie = [[NSHTTPCookie alloc] initWithProperties:jsonDict]; 
    [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie]; 

    return cookie!=nil; 
} 

- (void)clearSessionCookieAndRemoveFromKeyChain { 
    for (NSHTTPCookie *c in [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies) { 
     [[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:c]; 
    } 
    NSError *deleteError = nil; 
    [SFHFKeychainUtils deleteItemForUsername:WSC_username 
           andServiceName:WSC_serviceName 
             error:&deleteError]; 
} 
相關問題