Django默认提供了很好的跨域攻击保护(csrf)机制,采用常规的方法,我们几乎感觉不到这个机制的存在(好吧,还是需要在form中添加{% csrf_token %})。但是当我们期望能够以Ajax的方式向服务器提交表单的时候,问题就来了。
常规的HTTP GET方法被认为是安全的,不会做csrf检查,而POST、PUT、DELETE等方法被认为是有潜在危险的。因为我们没有按照Django的要求在请求头/内容域中包含X-CSRFToken及相应的正确的值。Django会直接返回一个Http 403的错误回来。
解决的办法其实也很简单,就是按照要求提供这个值即可。在Django文档中有非常详细的描述() ,也给除了一个非常简单的方法。
然而我们总不能将官方提供的代码到处粘贴吧,还是做一个简单的封装较好:
/** * 自动设置Django的csrf请求.要求jquery > 1.5.1 * 代码来自Django官网,做简单封装,直接引入此js即可. */(function(){ function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie != '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) == (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } var csrftoken = getCookie('csrftoken'); function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ crossDomain: false, // obviates need for sameOrigin test beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type)) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });})();
稍作解释:我们将官方提供的方法封装到一个匿名函数中,并通过在匿名函数外增加一对括号来强制js引擎将其视为一个表达式,返回值就是这个匿名函数,最后的一对括号则调用返回的这个匿名函数。
需要的时候只需要引入这个js即可。