我有一个iOS应用程序,需要登录到使用Django的现有站点,并需要CSRF令牌登录.我无法改变这一点.
我当前的尝试是将GET发送到服务器,该服务器将返回CSRF,然后将该cookie作为字符串抓取并将其附加到POST请求.
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:@"http://example.com"]]; [req setHTTPShouldHandleCookies:YES]; [NSURLConnection sendAsynchronousRequest:req queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { self.csrf_cookie = [[(NSHTTPURLResponse *)response allHeaderFields] valueForKey:@"Set-Cookie"]; [self postLoginCredentialsEmail:@"user@example.com" password:@"password"]; }]; - (void)postLoginCredentialsEmail:(NSString *)email password:(NSString *)password { NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:@"http://example.com/login"]]; [req addValue:(self.csrf_cookie != nil ? self.csrf_cookie : @"poo") forHTTPHeaderField:@"X-CSRFToken"]; [req setHTTPMethod:@"POST"]; NSString *postData = [NSString stringWithFormat:@"password=%@&;email=%@", password, email]; [req setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-type"]; [req setHTTPBody:[postData dataUsingEncoding:NSUTF8StringEncoding]]; [NSURLConnection sendAsynchronousRequest:req queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSLog(@"response from login: %@", response); }]; }
我正在获取cookie,但我仍然收到"不正确或丢失的CSRF令牌"错误.
我在这里看过其他帖子,这就是大部分代码来自但仍然失败的地方.
我已经比较了我的请求中服务器收到的内容与网站上的良好请求收到的内容,唯一的区别似乎是好的请求有一个HTTP头字段HTTP_X_CSRFTOKEN
只有CSRF令牌,而我的请求有格式'HTTP_X_CSRFTOKEN': 'csrftoken=tokenkey; expires=expirydate; Max-Age=age; Path=/, mws-track-id=somestuff; httponly; Path=/',
嗯,我设法利用NSHTTPCookieStorage然后通过这些迭代和当请求保存Cookie来解决该问题,cookie.name
是@"csrftoken"
我把cookie.value并将其分配给一个静态变量csrf_cookie.然后我将其附加到NSMutableURLRequest
标题字段X_CSRFTOKEN
,同时附加完整NSHTTPCookieStorage
这是一些代码:
// at the top static NSString *csrf_cookie; // in a function: NSURL *url = [[NSURL alloc] initWithString:@"http://example.com"]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; [request setHTTPShouldHandleCookies:YES]; [request setAllHTTPHeaderFields:[NSHTTPCookie requestHeaderFieldsWithCookies:[[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:url]]]; // make GET request are store the csrf [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:[(NSHTTPURLResponse *)response allHeaderFields] forURL:url]; [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:cookies forURL:url mainDocumentURL:nil]; // for some reason we need to re-store the CSRF token as X_CSRFTOKEN for (NSHTTPCookie *cookie in cookies) { if ([cookie.name isEqualToString:@"csrftoken"]) { csrf_cookie = cookie.value; break; } } // then in later requests: NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:url]; [req setHTTPMethod:@"POST"]; [req setAllHTTPHeaderFields:[NSHTTPCookie requestHeaderFieldsWithCookies:[[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:url]]]; [req addValue:csrf_cookie forHTTPHeaderField:@"X_CSRFTOKEN"];