Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/111.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用CSRF令牌从iOS发布到Django服务器_Ios_Django_Cookies_Django Csrf - Fatal编程技术网

使用CSRF令牌从iOS发布到Django服务器

使用CSRF令牌从iOS发布到Django服务器,ios,django,cookies,django-csrf,Ios,Django,Cookies,Django Csrf,我有一个iOS应用程序,需要登录到使用Django的现有站点,并且需要CSRF令牌才能登录。我不能改变这一点 我当前的尝试是向服务器发送一个GET,它将返回一个CSRF,然后将该cookie作为字符串抓取并附加到POST请求中 NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:@"http://example.com"]]; [req setHTTPS

我有一个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\u X\u CSRFTOKEN
,而我的请求的格式是
'HTTP\u X\u CSRFTOKEN':'CSRFTOKEN=tokenkey;expires=到期日;最大年龄=年龄;路径=/,mws轨迹id=something;httponly;路径=/,

我成功地解决了这个问题,使用NSHTTPCookieStorage保存请求中的cookie,然后迭代这些cookie,当
cookie.name
@“csrftoken”
时,我获取cookie.value并将其分配给静态变量csrf\u cookie。然后,我将其附加到头字段
X_CSRFTOKEN
NSMutableURLRequest
,同时还附加完整的
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"];

为了完整起见,我将添加我的答案:

你必须用页眉写一份请愿书

X-CSRF-Token -> Fetch
(根据具体情况,您可能需要附加某种类型的身份验证)

在您的响应中,您将收到带有令牌的相同标头,例如:

X-CSRF-Token -> <Value>
X-CSRF-Token->

这是一些SAP Enterprise services中使用的方法,对于此Django one必须与相应API视图中的认证类中的会话身份验证相同。它将“禁用”此视图的Cookie,这意味着不再需要CSRF令牌

例如:

authentication_classes = [SessionAuthentication, BasicAuthentication, JSONWebTokenAuthentication]
变成

authentication_classes = [BasicAuthentication, JSONWebTokenAuthentication]

验证Charles Proxy发送/接收的内容,这对我解决网络问题是必不可少的(免费30天试用)。我能够查看客户端和服务器端的所有请求。还是不走运。我已经更新了这篇文章,在Charles中,这两篇文章的唯一区别在于,你可以在消息上设置断点,修改消息,然后按消息的方式发送消息。你可以试着看看差异是否是问题所在。它似乎甚至没有从iOS模拟器注册我的请求。我需要单独配置吗?关于如何让Charles工作的想法?(我看了文件,但什么也找不到)