我有一个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=/',
答案 0 :(得分:6)
我设法通过使用NSHTTPCookieStorage保存请求中的cookie来解决问题,然后遍历这些问题,当cookie.name
为@"csrftoken"
时,我使用了cookie.value并将其分配给静态变量csrf_cookie。然后我将其附加到标题字段NSMutableURLRequest
的{{1}},同时附加完整的X_CSRFTOKEN
这里有一些代码:
NSHTTPCookieStorage
答案 1 :(得分:1)
在相应的API视图中从 authentication_classes 中取消 SessionAuthentication 。它会"禁用"此视图的Cookie,表示 CSRF-token不再需要。
例如:
authentication_classes = [SessionAuthentication, BasicAuthentication, JSONWebTokenAuthentication]
成为
authentication_classes = [BasicAuthentication, JSONWebTokenAuthentication]
答案 2 :(得分:0)
为了完整起见,我将添加我的答案:
您必须使用标题
进行请愿X-CSRF-Token -> Fetch
(视情况而定,您可能需要附加某种类型的身份验证)
在您的回复中,您将收到与令牌相同的标头,例如:
X-CSRF-Token -> <Value>
这是某些SAP Enterprise服务中使用的方法,对于此Django one
必须相同