如何获取cookie并在其他请求(如POST)中使用它们(iOS)?

6

我的之前的问题是关于我每次使用网络服务,如发布链接或上传图片时都需要重新登录的问题。Philipe回答说我需要使用cookie而不是每次请求时进行登录。我发现了以下获取cookie的方法:

- (void)getCookies {

    NSHTTPURLResponse * response;
    NSError * error;
    NSMutableURLRequest *request;

    request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://MyWebsite.com/login.php"]
                                            cachePolicy:NSURLRequestReloadIgnoringCacheData
                                        timeoutInterval:120];
    NSData * data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

    NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]);
    NSArray * all = [NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:[NSURL URLWithString:@"http://MyWebsite.com/login.php"]];
    NSLog(@"%d", all.count);

    for (NSHTTPCookie *cookie in all) {
        NSLog(@"Name: %@ : Value: %@", cookie.name, cookie.value);
        NSLog(@"Comment: %@ : CommentURL: %@", cookie.comment, cookie.commentURL);
        NSLog(@"Domain: %@ : ExpiresDate: %@", cookie.domain, cookie.expiresDate);
        NSLog(@"isHTTPOnly: %c : isSecure: %c", cookie.isHTTPOnly, cookie.isSecure);
        NSLog(@"isSessionOnly: %c : path: %@", cookie.isSessionOnly, cookie.path);
        NSLog(@"portList: %@ : properties: %@", cookie.portList, cookie.properties);
        NSLog(@"version: %u", cookie.version);
    }
} 

我也找到了这段代码来使用这些cookies,但我不确定如何使用它:
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookies];

这是我使用RestKit API进行POST的方法:

- (IBAction)addLinkPressed:(UIButton *)sender {

        [RKClient clientWithBaseURLString:@"http://MyWebsite.com"];

        NSDictionary* params = [NSDictionary dictionaryWithObjectsAndKeys:
                                self.linkField.text, @"url",
                                self.linkTitleField.text, @"title",
                                self.linkSummaryField.text, @"summary",
                                nil];

        RKRequest *request = [[RKClient sharedClient] post:@"/send_link.php" params:params delegate:self];
        [request setUserData:@"sendLink"];   
}

问题:我应该存储哪些cookie属性来用于登录信息,应该把它放在代码的哪个位置?


还没有解决方案吗? - Fady Kamal
1
@FadyKamal 我发表了我的方法论,希望对你有所帮助。 - Hamid
1个回答

1
我通过一种低效的方式解决了这个问题。以下是我的方法: 首先,我尝试向Web服务提交文章,然后解析返回的HTML以查看是否成功发布。如果发布成功,我会向用户提供适当的消息,告诉他们您已成功发布,但如果发布不成功,则有两个原因:第一,发布执行期间出现错误;第二,用户未登录。我识别第一和第二个错误之间的区别的方法只是解析响应HTML。 以下是我用于此方法的代码(这是用户想要更改密码的时间)。
- (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error {
    NSRange range = [[error localizedDescription] rangeOfString:@"-1012"];
    if (range.length > 0){
        //First error occurs here
    }
    RKLogError(@"Hit error: %@", error);
}



- (IBAction)requestToChangePasswordPressed {
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.labelText = @"Loading";

    [RKClient clientWithBaseURLString:@"http://WebServiceDomain.com"];

    NSDictionary* params = [NSDictionary dictionaryWithObjectsAndKeys:
                            self.oldPasswordField.text, @"oldPassword",
                            self.passwordNew.text, @"newPassword",
                            self.confirmPasswordField.text, @"confirmPassword",
                            nil];

    RKRequest *request = [[RKClient sharedClient] post:@"/change_password.php" params:params delegate:self];
    [request setUserData:@"changePassword"];
    [self.view endEditing:YES];
    [MBProgressHUD hideHUDForView:self.view animated:YES];
}

- (void)autoLogin {

    [RKClient clientWithBaseURLString:@"http://WebServiceDomain.com"];
    [RKObjectManager sharedManager].client=[RKClient sharedClient];
    RKParams *parameters = [RKParams params];

    [parameters setValue:[[NSUserDefaults standardUserDefaults] objectForKey:@"defaultUsername"] forParam:@"username"];
    [parameters setValue:[[NSUserDefaults standardUserDefaults] objectForKey:@"defaultPassword"] forParam:@"password"];

    [[RKClient sharedClient] setAuthenticationType:RKRequestAuthenticationTypeHTTP];
    // because we have two POSTs and we want to use the same method for both of the for didLoadResponse: we set the UserDate like bellow
    RKRequest *request = [[RKClient sharedClient] post:@"/login.php" params:parameters delegate:self];
    [request setUserData:@"login"];
}


- (void)request:(RKRequest*)request didLoadResponse:(RKResponse*)response
{
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.labelText = @"Loading";

    id userData = [request userData];
    if ([userData isEqual:@"login"]) {

        if ([request isGET]) {
            // Handling GET /foo.xml

            if ([response isOK]) {
                // Success! Let's take a look at the data
                NSLog(@"Retrieved XML: %@", [response bodyAsString]);
            }

        } else if ([request isPOST]) {

            // Handling POST /other.json
            if ([response isJSON]) {
                NSLog(@"Got a JSON response back from our POST!");
            }

        } else if ([request isDELETE]) {

            // Handling DELETE /missing_resource.txt
            if ([response isNotFound]) {
                NSLog(@"The resource path '%@' was not found.", [request resourcePath]);
            }
        }
    }

    else if ([userData isEqual:@"sendLink"]) {
        NSData *addLinksHtmlData = response.body;

        // 2
        TFHpple *addlinksParser = [TFHpple hppleWithHTMLData:addLinksHtmlData];

        // 3
        NSString *errorLinksXpathQueryString = @"//div[@class='errorBox']/ul/li";
        NSArray *errorLinksNodes = [addlinksParser searchWithXPathQuery:errorLinksXpathQueryString];


        // 4
        NSMutableArray *newErrorLinks = [[NSMutableArray alloc] initWithCapacity:0];
        for (TFHppleElement *element in errorLinksNodes) {
            // 5
            AllModels *errorTitle = [[AllModels alloc] init];
            [newErrorLinks addObject:errorTitle];

            // 6
            errorTitle.errorTitle = [[element firstChild] content];
        }

        // 8
        self.linkErrorObjects = newErrorLinks;



        NSString *successLinksXpathQueryString = @"//div[@class='successBox']";
        NSArray *successLinksNodes = [addlinksParser searchWithXPathQuery:successLinksXpathQueryString];


        // 4
        NSMutableArray *newSuccessLinks = [[NSMutableArray alloc] initWithCapacity:0];
        for (TFHppleElement *element in successLinksNodes) {
            // 5
            AllModels *successTitle = [[AllModels alloc] init];
            [newSuccessLinks addObject:successTitle];

            // 6
            successTitle.successTitle = [[element firstChild] content];
        }

        // 8
        self.linkSuccessObjects = newSuccessLinks;

    }


    else {

        NSLog(@"HTTP status code:     %d", response.statusCode);
        NSLog(@"HTTP status message:  %@", [response localizedStatusCodeString]);
        NSLog(@"Header fields: %@", response.allHeaderFields);
        NSLog(@"Body: %@", response.bodyAsString);


        NSData *HtmlData = response.body;

        // 2
        TFHpple *addParser = [TFHpple hppleWithHTMLData:HtmlData];

        // 3
        NSString *errorXpathQueryString = @"//div[@class='errorBox']/ul/li";
        NSArray *errorNodes = [addParser searchWithXPathQuery:errorXpathQueryString];


        // 4
        NSMutableArray *newError = [[NSMutableArray alloc] initWithCapacity:0];
        for (TFHppleElement *element in errorNodes) {
            // 5
            AllModels *errorTitle = [[AllModels alloc] init];
            [newError addObject:errorTitle];

            // 6
            errorTitle.errorTitle = [[element firstChild] content];
        }

        // 8
        self.ErrorObjects = newError;



        NSString *successXpathQueryString = @"//div[@class='successBox']";
        NSArray *successNodes = [addParser searchWithXPathQuery:successXpathQueryString];


        // 4
        NSMutableArray *newSuccess = [[NSMutableArray alloc] initWithCapacity:0];
        for (TFHppleElement *element in successNodes) {
            // 5
            AllModels *successTitle = [[AllModels alloc] init];
            [newSuccess addObject:successTitle];

            // 6
            successTitle.successTitle = [[element firstChild] content];
        }

        // 8
        self.successObjects = newSuccess;

        [self errorCheck];
    }
    [MBProgressHUD hideHUDForView:self.view animated:YES];
    [MBProgressHUD hideHUDForView:self.view animated:YES];
}



- (void)errorCheck {

    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.labelText = @"Loading";

    if(self.errorObjects.count > 0) {
        AllModels *errorlink = [self.errorObjects objectAtIndex:0];
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"There is a problem" message:errorlink.errorTitle delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil , nil];
        [alert show];
    }
    else {


        if(self.linkErrorObjects.count > 0) {
            [self autoLogin];
            [self requestToChangePasswordPressed];
        }

        else {
            AllModels *successlink = [self.successObjects objectAtIndex:0];
            self.successLabel.hidden = NO;
            self.successLabel.text = successlink.successTitle;
            NSLog(@"Success Title:  %@",successlink.successTitle);


            [UIView animateWithDuration:3.0
                                  delay:0.0
                                options:UIViewAnimationOptionBeginFromCurrentState
                             animations:^{ self.successLabel.alpha = 0.0; }
                             completion:^(BOOL fin) { if (fin) [self.successLabel removeFromSuperview]; }];


            [self performSelector:@selector(dismissModalViewController) withObject:nil afterDelay:1.0];
        }

    }
    [MBProgressHUD hideHUDForView:self.view animated:YES];
    [MBProgressHUD hideHUDForView:self.view animated:YES];
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接