2014-12-04 2 views
7

일시적인 NSURLSessions를 사용하여 내 앱 내의 여러 작업에 별도의 쿠키 처리를 제공하려고합니다. 이러한 작업은 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의 출력은 항상 : 1 NSHTTPCookieAcceptPolicyNever의 값입니다

Ephemeral <NSHTTPCookieStorage cookies count:0> 
1 

이 (NSHTTPCookieAcceptPolicyAlways 0 예상)

여기 내 코드입니다. 응답의 헤더가 있습니다.

NSHTTPCookieStorage가 세션이 살아있는 동안 내 쿠키를 기억하게하려면 어떻게해야합니까? 나는 필요가없고 끈기를 원하지 않는다. 쿠키를 메모리에 보관하여 동일한 세션에서 추가 요청을 위해 쿠키를 다시 사용하고자합니다.

답변

2

임시 세션이 쿠키를 저장하지 않는 것처럼 보입니다. eskimo1 says on the devforums :

ISTR 임시 세션 구성이 사람들이 문서를 기반으로 기대하는 방식으로 작동하지 않습니다. 나는 이것에 관해 상세히보고있는 에 결코 도착하지 않았다. 그러나 그것은 당신과 같게 보인다. 이 문제에 관해 버그를 보내 주어야합니다. 구현 및 문서화가 동기화되어 있으므로 이 분명하므로이 중 하나를 수정해야합니다.

1

iOS9 ephemeralSessionConfiguration이 예상대로 작동하는 것처럼 보입니다. 하지만 iOS8에서는 쿠키 저장소가 정책에 대해 Never를 반환하고 재설정 할 수없는 것처럼 보입니다. 구현은 메모리 전용 대신 개인 클래스 이름에도 불구하고 저장소가없는 것처럼 보입니다.

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에 필요한 안된다). 아마도 몇 가지 버그가있을 것입니다 ... 나는 데모 용으로 이것을 필요로했고, 그것을 위해 충분히 잘 작동했습니다. 그러나 어떤 일이 일어나면 고치기가 너무 어렵지 않아야합니다.

관련 문제