3

我正在发送带有存储在设备端的 session-cookie 的 http 请求。问题是我想在应用程序终止时保留它。但似乎我的应用程序的所有 cookie 都被删除了。我在模拟器和设备上都试过了,他们得到了相同的行为。

是否有任何 iOS 方法可以防止此 cookie 删除?如果没有,如何将其保存到磁盘并恢复?

为了安全起见,我打算将此 cookie 保存在 iOS 钥匙串中。而且我认为所有 NSHTTPCookie 属性都可以安全地转换为 NSString。所以我目前的想法是从NSHTTPCookie -> NSDictionary -> String -> Save in Keychain转换,然后向后使用获取原始cookie。问题是我不想经历转换NSDictionary -> String和解析String -> NSDictionary的麻烦。

4

3 回答 3

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];
}
于 2012-05-22T10:47:46.947 回答
1

假设你有一个 NSHTTPURLResponse,你可以得到一个像这样的 cookie 数组:

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

responseNSHTTPURLResponse在哪里。

您将在 NSURLConnectionDelegate 的这 2 个方法中获得 NSURLResponses

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

NSHTTPCookie 有一个properties返回 的属性NSDictionary,所以你可以保存它们。然后可以使用相同的字典创建它们-initWithProperties:

要发送它们,您需要为 a 的 Cookie 标头创建自己的字符串NSURLRequest。就像是:

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

request一个在哪里NSMutableURLRequest

您还应该确保停止 iOS 管理 cookie 本身:

[request setHTTPShouldHandleCookies:NO];
于 2012-05-21T11:42:09.957 回答
1

===== 总结 =====

好吧,我将创建另一个答案,以总结保持 NSDictionary 的可能方法(当然不包含对象!)。

最简单的方法是使用 NSDictionary 的writeToFile:方法。这将生成一个 plist 文件。(也可在 NSArray 中使用)如果您担心安全性,请将数组加密为 NSData 对象并写入。

另一种方法(虽然不是最快的方法)是使用工具将 NSDictionary 转换为字符串格式,例如 JSON 或 XML。您可以将此字符串保存在 iOS 钥匙串中,以便以后轻松检索。(SFHFKeychainUtils非常适合帮助处理钥匙串)。使用钥匙串的好处是它会自动加密。

于 2012-05-23T11:17:14.243 回答