我想将我的iOS应用程序中的数据发布到我的Django服务器 - 在URL中对其进行编码只是不切实际。我想在没有表单的情况下执行此操作,只需发送JSON数据并获取JSON数据。当我尝试时,我遇到了这个错误:
Forbidden (CSRF token missing or incorrect.)
对于开发,我现在通过声明我的查看方法为@csrf_exempt
来解决这个问题,但我担心这对生产来说是不安全的。 是否我还宣布方法@login_required
?
假设它不安全,我该如何解决?我理解在HTML模板中使用{% csrf_token %}
的方法 - 我在其他Django应用程序中使用过 - 但是,我实际上并没有使用表单,也不希望如此。我只是将我的请求数据编码在JSON字典中,然后获取JSON字典。这是客户方的相关部分:
NSData *data = [NSJSONSerialization dataWithJSONObject:dictWithMyData options:NSJSONWritingPrettyPrinted error:&error];
if (!data) {
if (error)
NSLog(@"NSJSONSerialization error = %@", [error localizedDescription]);
return NO;
}
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:myServerMethodUrl] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:timeout];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:data];
NSURLResponse *urlResponse = nil;
NSData *urlData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error];
if (error) {
NSLog(@"NSURLConnection error = %@", [error localizedDescription]);
return NO;
}
这是相关的服务器部分:
@login_required
def my_server_method(request):
data = simplejson.loads(request.body)
R = {}
# Do stuff with the data here and generate a response with JSON data in R
....
return HttpResponse(json.dumps(R), content_type="application/json")
根据我对CSRF机制的了解,CSRF令牌对整个会话都有效。所以我认为我可以通过以下方式完成这项工作:a)在身份验证时,将CSRF令牌传递给我的iOS客户端,然后b)在发布数据时包含令牌。这是我尝试的方式。
在服务器中进行身份验证后,我会找到带有此功能的CSRF令牌并将其发送给客户端:
session_csrf_token = django.middleware.csrf.get_token(request)
我尝试通过修改上面的客户端代码来传回它。首先,我使用session_csrf_token
(在登录时在客户端上存储为_csrfToken
)扩充我发送的数据:
NSMutableDictionary *dictCSRF = [NSMutableDictionary dictionaryWithDictionary:dictWithMyData];
[dictCSRF setObject:_csrfToken forKey:@"csrfmiddlewaretoken"];
NSData *data = [NSJSONSerialization dataWithJSONObject:dictCSRF options:NSJSONWritingPrettyPrinted error:error];
然后我像这样扩充请求标题:
[request setValue:_csrfToken forHTTPHeaderField:@"X-CSRF-Token"];
但它不起作用。我得到了相同的" CSRF令牌丢失或不正确"错误。
有关如何使其发挥作用的任何想法?