Deepak Sharma
Deepak Sharma

Reputation: 6585

NSHTTPCookieStorage for same URL but different users

May be this is a dumb question, but I want to store cookies for same url but different for usernames. How can this be achieved using NSHTTPCookieStorage ? This is how I store cookies from response.

        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;

        NSDictionary *headerFields = [httpResponse allHeaderFields];


        NSArray* cookies = [NSHTTPCookie
                            cookiesWithResponseHeaderFields:headerFields
                            forURL:[NSURL URLWithString:@""]];

        for (NSHTTPCookie *cookie in cookies) {
            [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
        }

       NSString *urlString = ...;

        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:cookies forURL:[NSURL URLWithString:urlString] mainDocumentURL:nil];

Upvotes: 1

Views: 1340

Answers (3)

liaogang
liaogang

Reputation: 518

@interface NSHTTPCookieStorage (ApplePrivateHeader)
-(id)_initWithIdentifier:(id)arg1 private:(BOOL)arg2;
@end

@interface User()
@property (nonatomic, strong) NSHTTPCookieStorage *myHTTPCookieStorage;
@end

@implementation User

-(instancetype)init
{
    self = [super init];
    if (self) {
         //the [NSHTTPCookieStorage init] will generate a instance with no inner `NSHTTPCookieStorageInternal`, so.
        _myHTTPCookieStorage = [[NSHTTPCookieStorage alloc] _initWithIdentifier: @"user_id_xxx" private:0];
        _myHTTPCookieStorage.cookieAcceptPolicy = NSHTTPCookieAcceptPolicyAlways;
    }
    return self;
}

-(void)httpTask{
    NSURLSessionConfiguration *c =[NSURLSessionConfiguration ephemeralSessionConfiguration];

    c.HTTPCookieStorage = _myHTTPCookieStorage;

    [[[NSURLSession sessionWithConfiguration: c] dataTaskWithRequest:request completionHandler:nil] resume];
}


// load from file
-(void)(id)initWithCoder:(NSCoder *)aDecoder{
    NSArray<NSHTTPCookie*> *cookies = [aDecoder decodeObjectForKey:@"cookies"];

    for (NSHTTPCookie *cookie in cookies) {
        [_myHTTPCookieStorage setCookie: cookie];
    }
}

//save to file
- (void)encodeWithCoder:(NSCoder *)aCoder
    [aCoder encodeObject:_myHTTPCookieStorage.cookies forKey: @"cookies"];
}


@end

Upvotes: 0

ricardopereira
ricardopereira

Reputation: 11683

You can have separate cookie stores (i.e. multiple users) for the same URL using the sharedCookieStorage(forGroupContainerIdentifier:).

You can obtain a common cookie storage by using that method and use it in a URLSession.

Example:

NSHTTPCookieStorage for same URL but different users

let configuration = URLSessionConfiguration.default.copy() as! URLSessionConfiguration
configuration.httpCookieStorage = HTTPCookieStorage.sharedCookieStorage(forGroupContainerIdentifier: UUID().uuidString)
configuration.httpCookieStorage?.cookieAcceptPolicy = .always
let sessionForCurrentUser = URLSession(configuration: configuration)
let task = sessionForCurrentUser.dataTask(with: URL(string: "https://foo.com/feature")!)
// ...

So, if you want to support multiple users, then create a common group identifier for each user.

In case the app starts with a guest user, then you need to "upgrade" the cookies storage when the user signs in. Something like:

// Upgrade from Guest user to Paid user
let guestCookieStorage = HTTPCookieStorage.sharedCookieStorage(forGroupContainerIdentifier: guestId)
let userCookieStorage = HTTPCookieStorage.sharedCookieStorage(forGroupContainerIdentifier: user.uniqueIdentifier)
for cookie in guestCookieStorage.cookies ?? [] {
    userCookieStorage.setCookie(cookie)
}

Upvotes: 1

dgatwood
dgatwood

Reputation: 10417

If I understand you correctly, you want to have separate sets of cookies for different users. If so, then you should:

  1. Create your own custom cookie storage class (probably just a dictionary with the base URL as the key and an array of cookies as the value) and store cookies there in addition to using the sharedHTTPCookieStorage object.

  2. When you change users, wipe the shared cookie storage and copy the cookies from the new user's cookie jar (or selectively remove every cookie created by that user from the shared jar).

If I misunderstood you and you want to store one particular cookie outside of the shared cookie storage for some reason:

  1. Create an NSURLSession object based on a configuration with a nil cookie jar (disabling automatic cookie storage).

  2. Store the cookies into a cookie jar like you're doing above (which may or may not be the shared cookie jar), but leave out the ones you want to avoid storing.

  3. Write a method to adds the cookies from that cookie jar to an NSURLRequest object.

  4. Always remember to call that method on your URL request objects before you create tasks with them.

This all assumes NSURLSession, of course. I don't think there's a way to control cookie storage with NSURLConnection. All cookies get stored in the cookie jar, period, AFAIK.

Upvotes: 2

Related Questions