2014-12-04 34 views
7

我想在我的應用程序中使用短暫的NSURLSessions爲幾個任務提供單獨的cookie處理。這些任務不直接綁定到UI。 問題:無論我做什麼,臨時NSHTTPCookieStorage的cookieAcceptPolicy仍然是NSHTTPCookieAcceptPolicyNever如何爲短暫的NSURLSession設置cookieAcceptPolicy

這裏是我的代碼:

// use a pure in-memory configuration with its own private cache, cookie, and credential store 
__block NSURLSessionConfiguration* config = [NSURLSessionConfiguration ephemeralSessionConfiguration]; 

// do anything to accept all cookies 
config.HTTPShouldSetCookies = YES; 
config.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyAlways; 
config.HTTPCookieStorage.cookieAcceptPolicy = NSHTTPCookieAcceptPolicyAlways; 

__block NSURLSession* session = [NSURLSession sessionWithConfiguration:config]; 

NSURLSessionDataTask* task = [session dataTaskWithURL:[NSURL URLWithString:@"https://test.cgmlife.com/Catalogs"] 
            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
             NSHTTPCookieStorage* cookies = session.configuration.HTTPCookieStorage; 
             NSLog(@"%@", cookies); 
             NSLog(@"%lu", cookies.cookieAcceptPolicy); 
            }]; 
[task resume]; 

從NSLog的輸出始終:

Ephemeral <NSHTTPCookieStorage cookies count:0> 
1 

其中1是NSHTTPCookieAcceptPolicyNever的值(NSHTTPCookieAcceptPolicyAlways預期0)。響應中的標題在那裏。

當會話還活着時,我能做些什麼來讓NSHTTPCookieStorage記住我的cookies?我不需要也不想要任何持久性。我只是想讓cookies保留在內存中,以便在同一會話中用於進一步的請求。

回答

2

它看起來像臨時會話不會存儲有史以來的餅乾。 eskimo1 says on the devforums

ISTR是短暫的會話配置不工作是 人指望基於文檔的方式。我從來沒有到過 詳細看這個,但它看起來像你。你應該提交 這個bug;該實現和文檔清晰地顯示出 的同步,所以其中一個需要修復。

1

它看起來像iOS9 ephemeralSessionConfiguration按預期工作。不過,在iOS8上,似乎Cookie存儲器的策略返回「從不」,並且無法重置。儘管存在專用類名稱,但實現似乎是無存儲的,而不是僅存儲器。

對於iOS8,我能夠用一個基本的實現來代替它,它似乎能夠工作(至少在模擬器中進行輕度測試)。實現具有任務對象的新方法非常重要。

#import <Foundation/Foundation.h> 
@interface MemoryCookieStorage : NSHTTPCookieStorage 
@property (nonatomic, strong) NSMutableArray *internalCookies; 
@property (atomic, assign) NSHTTPCookieAcceptPolicy policy; 
@end 

@implementation MemoryCookieStorage 

- (id)init 
{ 
    if (self = [super init]) { 
     _internalCookies = [NSMutableArray new]; 
     _policy = NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain; 
    } 
    return self; 
} 

- (NSHTTPCookieAcceptPolicy)cookieAcceptPolicy { 
    return self.policy; 
} 
- (void)setCookieAcceptPolicy:(NSHTTPCookieAcceptPolicy)cookieAcceptPolicy { 
    self.policy = cookieAcceptPolicy; 
} 

- (NSUInteger)_indexOfCookie:(NSHTTPCookie *)target 
{ 
    return [_internalCookies indexOfObjectPassingTest:^BOOL(NSHTTPCookie *cookie, NSUInteger idx, BOOL *stop) { 
     return ([target.name caseInsensitiveCompare:cookie.name] == NSOrderedSame && 
       [target.domain caseInsensitiveCompare:cookie.domain] == NSOrderedSame && 
       (target.path == cookie.path || [target.path isEqual:cookie.path])); 
    }]; 
} 

- (void)setCookie:(NSHTTPCookie *)cookie 
{ 
    if (self.cookieAcceptPolicy != NSHTTPCookieAcceptPolicyNever) 
    { 
     @synchronized(_internalCookies) { 
      NSInteger idx = [self _indexOfCookie:cookie]; 
      if (idx == NSNotFound) 
       [_internalCookies addObject:cookie]; 
      else 
       [_internalCookies replaceObjectAtIndex:idx withObject:cookie]; 
     } 
    } 
} 

- (void)deleteCookie:(NSHTTPCookie *)cookie 
{ 
    @synchronized(_internalCookies) { 
     NSInteger idx = [self _indexOfCookie:cookie]; 
     if (idx != NSNotFound) 
      [_internalCookies removeObjectAtIndex:idx]; 
    } 
} 

- (NSArray *)cookies 
{ 
    @synchronized(_internalCookies) { 
     return [_internalCookies copy]; 
    } 
} 

static BOOL HasCaseSuffix(NSString *string, NSString *suffix) 
{ 
    return [string rangeOfString:suffix options:NSCaseInsensitiveSearch|NSAnchoredSearch|NSBackwardsSearch].length > 0; 
} 
static BOOL IsDomainOK(NSString *cookieDomain, NSString *host) 
{ 
    return ([cookieDomain caseInsensitiveCompare:host] == NSOrderedSame || 
      ([cookieDomain hasPrefix:@"."] && HasCaseSuffix(host, cookieDomain)) || 
      (cookieDomain && HasCaseSuffix(host, [@"." stringByAppendingString:cookieDomain]))); 
} 
- (NSArray *)cookiesForURL:(NSURL *)URL 
{ 
    NSMutableArray *array = [NSMutableArray new]; 
    NSString *host = URL.host; 
    NSString *path = URL.path; 

    @synchronized(_internalCookies) 
    { 
     for (NSHTTPCookie *cookie in _internalCookies) 
     { 
      if (!IsDomainOK(cookie.domain, host)) 
       continue; 

      BOOL pathOK = cookie.path.length == 0 || [cookie.path isEqual:@"/"] || [path hasPrefix:cookie.path]; 
      if (!pathOK) 
       continue; 

      if (cookie.isSecure && [URL.scheme caseInsensitiveCompare:@"https"] != NSOrderedSame) 
       continue; 

      if ([cookie.expiresDate timeIntervalSinceNow] > 0) 
       continue; 

      [array addObject:cookie]; 
     } 
    } 

    array = (id)[array sortedArrayUsingComparator:^NSComparisonResult(NSHTTPCookie *c1, NSHTTPCookie *c2) { 
     /* More specific cookies, i.e. matching the longest portion of the path, come first */ 
     NSInteger path1 = c1.path.length; 
     NSInteger path2 = c2.path.length; 
     if (path1 > path2) 
      return NSOrderedAscending; 
     if (path2 > path1) 
      return NSOrderedDescending; 
     return [c1.name caseInsensitiveCompare:c2.name]; 
    }]; 

    return array; 
} 

- (NSArray *)sortedCookiesUsingDescriptors:(NSArray *)sortOrder 
{ 
    return [[self cookies] sortedArrayUsingDescriptors:sortOrder]; 
} 

- (void)getCookiesForTask:(NSURLSessionTask *)task completionHandler:(void (^) (NSArray *taskCookies))completionHandler 
{ 
    NSArray *urlCookies = [self cookiesForURL:task.currentRequest.URL]; 
    completionHandler(urlCookies); 
} 

- (void)setCookies:(NSArray *)newCookies forURL:(NSURL *)URL mainDocumentURL:(NSURL *)mainDocumentURL 
{ 
    NSString *host = mainDocumentURL.host; 
    for (NSHTTPCookie *cookie in newCookies) 
    { 
     switch (self.cookieAcceptPolicy) 
     { 
      case NSHTTPCookieAcceptPolicyAlways: 
       [self setCookie:cookie]; 
       break; 
      case NSHTTPCookieAcceptPolicyNever: 
       break; 
      case NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain: 
       if (IsDomainOK(cookie.domain, host)) 
        [self setCookie:cookie]; 
       break; 
     } 
    } 
} 

- (void)storeCookies:(NSArray *)taskCookies forTask:(NSURLSessionTask *)task 
{ 
    NSURL *mainURL = task.currentRequest.mainDocumentURL ?: task.originalRequest.mainDocumentURL ?: task.originalRequest.URL; 
    [self setCookies:taskCookies forURL:task.currentRequest.URL mainDocumentURL:mainURL]; 
} 

@end 

應該可以創建臨時會話,看是否HTTPCookieStorage需要與上面的類的實例來代替之後測試sessionConfiguration.HTTPCookieStorage.cookieAcceptPolicy == NSHTTPCookieAcceptPolicyNever(不應該需要它iOS9)。有可能有一些錯誤...我只需要這個演示,它運作得很好。但如果出現問題,他們不應該太難解決。