我在Django中遇到的CSRF令牌机制有问题,只出现在Firefox和Internet Explorer中(Chrome似乎工作得很好)。我的网站提供了一个页面,该页面在页面为ready()
后执行AJAX调用。发出AJAX调用后,我收到 403 Forbidden 错误,指出 CSRF验证失败。请求已中止。错误页面给出的原因是未设置 CSRF cookie。
我已经看过Django CSRF check failing with an Ajax POST request了,我正在按照那里接受的答案。但是,我仍然在3个浏览器中的2个中看到问题。
当我检查此调用的标头时,我看到正确设置了csrftoken
,但该值与页面中设置的值不匹配!
(我错误地认为这些值不匹配.Firefox中的“查看源代码”选项显然会重新加载页面,而不是显示您正在查看的页面的来源。)
我的服务器是按照this article设置的,虽然我现在使用SQLite而不是Postgres。 为什么在令牌正确传递时我会收到403错误?
这是我的AJAX电话:
$.ajax({
beforeSend: function(xhr, settings) {
csrftoken = getCookie('csrftoken');
if(!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
url: "{% url 'cap_plan:ajax_get_chart_data' %}",
type: "POST",
success: drawChart,
error: function(xhr, errmsg, err) {
// TODO: Do something better in the error case
console.log("AJAX Error!");
console.log(xhr.status + ": " + xhr.responseText);
}
});
getCookie()
和csrfSafeMethod
例程是official CSRF documentation中列出的完整例程。
以下是此次通话所使用的网址规则:
url(r'^ajax/get_chart_data/$', ajax_get_chart_data, name='ajax_get_chart_data'),
以下是整个页面各自视图的简化视图:
@ensure_csrf_cookie
def cap_plan_overview(request):
return render_to_response('cap-plan-overview.html',
{}, context_instance=RequestContext(request))
AJAX调用本身的视图(再次,简化):
def ajax_get_chart_data(request):
if request.method == 'POST':
// Do a bunch of work getting data; put it in the response dict
return HttpResponse(
json.dumps(response),
content_type="application/json"
)
else:
return HttpResponse(
json.dumps({error: "Invalid AJAX call to ajax_get_chart_data"}),
content_type="application/json"