AFNetworking 支援cookies的解決方案

Kaitiren發表於2016-01-26

   AFNetworking是支援cookies,只不過它把這個邏輯交給了iOS 底層的api處理了。

   多話不說了,很討厭網上那些人云亦云的帖子,三人成虎!

  本次我們的專案重構,需要用到cookies,我直接給出解決方案吧:

(cookie使用支援的簡單思路是:首次請求時,伺服器取回cookies,然後每次請求時附加上cookie,如此反覆即可,至於cookies中有啥內容,我們不用關注,伺服器要就給她)

  我使用的是AFNetworking的AFHTTPClient進行網路訪問的,我就直接在AFHTTPClient.h新增兩個支援cookies的方法,一個是為post寫的,另一個是為get寫的。

1、在AFHTTPClient.h新增兩個支援cookies的方法,每次請求時,都傳送出本地cookies

1
2
3
4
5
 // add by block cheng
- (void)blockGetPath:(NSString *)path
     parameters:(NSDictionary *)parameters
        success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
        failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;

1
2
3
4
5
//add by block cheng
- (void)blockPostPath:(NSString *)path
      parameters:(NSDictionary *)parameters
         success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
         failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;

   其實現是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
- (void)blockGetPath:(NSString *)path
          parameters:(NSDictionary *)parameters
             success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
             failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
     
    if (!path) {
        path = @"";
    }
     
    NSArray *arcCookies = [NSKeyedUnarchiver unarchiveObjectWithData: [[NSUserDefaults standardUserDefaults] objectForKey: @"sessionCookies"]];
    NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
     
    for (NSHTTPCookie *cookie in arcCookies){
        [cookieStorage setCookie: cookie];
    }
     
    NSURL *dataUrl = [NSURL URLWithString:path relativeToURL:self.baseURL];
    NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:dataUrl];//id: NSHTTPCookie
    NSDictionary *sheaders = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
     
    NSString *charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
     
    __strong NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:dataUrl cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.f];
     
    [request setHTTPMethod:@"GET"];
    [request addValue:@"iOS" forHTTPHeaderField:@"User-Agent"];
    [request setValue:[NSString stringWithFormat:@"application/x-www-form-urlencoded; charset=%@", charset] forHTTPHeaderField:@"Content-Type"];
//    [request setHTTPBody:[AFQueryStringFromParametersWithEncoding(parameters, NSUTF8StringEncoding) dataUsingEncoding:NSUTF8StringEncoding]];
    [request setAllHTTPHeaderFields:sheaders];
 
     
    if (parameters) {
            dataUrl = [NSURL URLWithString:[[dataUrl absoluteString] stringByAppendingFormat:[path rangeOfString:@"?"].location == NSNotFound ? @"?%@" : @"&%@", AFQueryStringFromParametersWithEncoding(parameters, self.stringEncoding)]];
            [request setURL:dataUrl];
    }
    AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
    [self enqueueHTTPRequestOperation:operation];
 
 
}

  post實現是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
- (void)blockPostPath:(NSString *)path
           parameters:(NSDictionary *)parameters
              success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
              failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
    if (!path) {
        path = @"";
    }
    NSArray *arcCookies = [NSKeyedUnarchiver unarchiveObjectWithData: [[NSUserDefaults standardUserDefaults] objectForKey: @"sessionCookies"]];
    NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
     
    for (NSHTTPCookie *cookie in arcCookies){
        [cookieStorage setCookie: cookie];
    }
     
    NSURL *dataUrl = [NSURL URLWithString:path relativeToURL:self.baseURL];
    NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:dataUrl];//id: NSHTTPCookie
    NSDictionary *sheaders = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
     
    NSString *charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
     
    __strong NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:dataUrl cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.f];
     
    [request setHTTPMethod:@"Post"];
    [request addValue:@"iOS" forHTTPHeaderField:@"User-Agent"];
    [request setValue:[NSString stringWithFormat:@"application/x-www-form-urlencoded; charset=%@", charset] forHTTPHeaderField:@"Content-Type"];
//    [request setHTTPBody:[AFQueryStringFromParametersWithEncoding(parameters, NSUTF8StringEncoding) dataUsingEncoding:NSUTF8StringEncoding]];
    [request setAllHTTPHeaderFields:sheaders];
 
    if (parameters) {
        NSString *charset = (__bridge NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(self.stringEncoding));
        NSError *error = nil;
         
        switch (self.parameterEncoding) {
            case AFFormURLParameterEncoding:;
                [request setValue:[NSString stringWithFormat:@"application/x-www-form-urlencoded; charset=%@", charset] forHTTPHeaderField:@"Content-Type"];
                [request setHTTPBody:[AFQueryStringFromParametersWithEncoding(parameters, self.stringEncoding) dataUsingEncoding:self.stringEncoding]];
                break;
            case AFJSONParameterEncoding:;
                [request setValue:[NSString stringWithFormat:@"application/json; charset=%@", charset] forHTTPHeaderField:@"Content-Type"];
                [request setHTTPBody:[NSJSONSerialization dataWithJSONObject:parameters options:0 error:&error]];
                break;
            case AFPropertyListParameterEncoding:;
                [request setValue:[NSString stringWithFormat:@"application/x-plist; charset=%@", charset] forHTTPHeaderField:@"Content-Type"];
                [request setHTTPBody:[NSPropertyListSerialization dataWithPropertyList:parameters format:NSPropertyListXMLFormat_v1_0 options:0 error:&error]];
                break;
        }
         
        if (error) {
            NSLog(@"%@ %@: %@", [self class], NSStringFromSelector(_cmd), error);
        }
     
    }
     
    AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
    [self enqueueHTTPRequestOperation:operation]; 
 
}

  對應的使用方法分別是:

2、每次請求返回時,儲存cookie,以供以後使用

 get的使用方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**
 *執行get請求,支援cookie
 *TODO: 需要完善
 **/
-(void)asynchronousCookiesGET:(NSString *)path witParams:(NSMutableDictionary *)params
{
    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:BASE_URL_SESSION]];
    self.client = httpClient;
    [httpClient release];
    [self.client blockGetPath:path parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject)
     {
         D_END;
         LogNET(@"------------------------GET--->------------------------------");
         LogNET(@"netWorking url:: %@",operation.request.URL.absoluteString);
         LogNET(@"netWorking params:: %@",params);
         LogNET(@"net working statuCode:: %d",operation.response.statusCode);
         LogNET(@"net working responseString:: %@",operation.responseString);
         LogNET(@"------------------------GET---<-----------------------------");
          
         NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
         for (NSHTTPCookie *cookie in cookies) {
             // Here I see the correct rails session cookie
             NSLog(@"Block cookie: %@", cookie);
         }
          
         NSData *cookiesData = [NSKeyedArchiver archivedDataWithRootObject: [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]];
         NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
         [defaults setObject: cookiesData forKey: @"sessionCookies"];
         [defaults synchronize];
          
          
    //handle server return data;
          
          
          
     }failure:^(AFHTTPRequestOperation *operation, NSError* error)
     {
         LogNET(@"------------------------GET--->------------------------------");
         LogNET(@"netWorking url:: %@",operation.request.URL.absoluteString);
         LogNET(@"net working statuCode:: %d",operation.response.statusCode);
         LogNET(@"net working responseString:: %@",operation.responseString);
         LogNET(@"------------------------GET---<-----------------------------");
          
         WebExceptionEntity* exception = [[WebExceptionEntity alloc] initWithExceptionString:operation.responseString withStatusCode:operation.response.statusCode withError:error];
         self.webException= exception;
         [exception release];
          
         if (self.exceptionBlock)
         {
             self.exceptionBlock(self,self.webException);
         }
          
     }
     ];
 
 
     
     
}

Post的使用方式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
 *執行post請求:支援cookie的版本
 **/
-(void)asynchronousCookiesPost:(NSString *)path
              witParams:(NSMutableDictionary *)params
{
    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:BASE_URL_SESSION]];
    self.client = httpClient;
    [httpClient release];
    if (self.preBlcok) {
        self.preBlcok(self);
    }
    [self.client blockPostPath:path parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject)
     {
         D_END;
         LogNET(@"------------------------POST--->------------------------------");
         LogNET(@"netWorking url:: %@",operation.request.URL.absoluteString);
         LogNET(@"netWorking params:: %@",params);
         LogNET(@"net working statuCode:: %d",operation.response.statusCode);
         LogNET(@"net working responseString:: %@",operation.responseString);
         LogNET(@"------------------------POST---<-----------------------------");
          
         NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
         for (NSHTTPCookie *cookie in cookies) {
             // Here I see the correct rails session cookie
             NSLog(@"cookie: %@", cookie);
         }
          
         NSData *cookiesData = [NSKeyedArchiver archivedDataWithRootObject: [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]];
         NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
         [defaults setObject: cookiesData forKey: @"sessionCookies"];
         [defaults synchronize];
     
         //handle server return data
     }failure:^(AFHTTPRequestOperation *operation, NSError* error)
     {
         LogNET(@"------------------------POST--->------------------------------");
         LogNET(@"netWorking url:: %@",operation.request.URL.absoluteString);
         LogNET(@"net working statuCode:: %d",operation.response.statusCode);
         LogNET(@"net working responseString:: %@",operation.responseString);
         LogNET(@"------------------------POST---<-----------------------------");
         WebExceptionEntity* exception = [[WebExceptionEntity alloc] initWithExceptionString:operation.responseString withStatusCode:operation.response.statusCode withError:error];
         self.webException= exception;
         [exception release];
          
         if (self.exceptionBlock)
         {
             self.exceptionBlock(self,self.webException);
         }
          
     }];
     
     
}

測試執行:

1
2
3
4
5
6
2014-02-14 10:00:53.465 TripPlus[15245:60b] cookie: <NSHTTPCookie version:0 name:"ssid" value:"79244stsh4p3shv1ftd1125d90" expiresDate:(null) created:2014-02-14 02:00:53 +0000 (4.14036e+08) sessionOnly:TRUE domain:"192.168.1.199" path:"/" isSecure:FALSE>
 
//--使用cookies
TPTripPlusDetailViewController.m:141      .... 開始請求
AFHTTPClient.m:706  post  add cookie:<NSHTTPCookie version:0 name:"acb5f57bfaec0550abdb337d5e8f0f40" value:"1febc174d86a8f5473af180658a7d9369b1e35daa%3A4%3A%7Bi%3A0%3Bs%3A1%3A%221%22%3Bi%3A1%3Bs%3A17%3A%22test%40joviainc.com%22%3Bi%3A2%3Bi%3A2592000%3Bi%3A3%3Ba%3A0%3A%7B%7D%7D" expiresDate:2014-03-16 02:00:50 +0000 created:2001-01-01 00:00:01 +0000 (1) sessionOnly:FALSE domain:"192.168.1.199" path:"/" isSecure:FALSE>
AFHTTPClient.m:706  post  add cookie:<NSHTTPCookie version:0 name:"ssid" value:"79244stsh4p3shv1ftd1125d90" expiresDate:(null) created:2001-01-01 00:00:01 +0000 (1) sessionOnly:TRUE domain:"192.168.1.199" path:"/" isSecure:FALSE>

從結果可看出,完美執行。

相關文章