(Django)CSRF Verification用于在Chrome中使用但不支持Firefox的AJAX请求
正如标题所述,我的(Django)CSRFvalidation在Chrome中运行但不在Firefox中,我想知道为什么我可以解决这个问题。
我有这个包含在我的base.html文件的head标记中,我的应用程序中的所有其他文件都扩展到该标记:
base.html,head标记的底部
$(document).ready(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({ beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } }); });
我将这段代码放在一个名为browse.js的文件中,该文件需要向我自己的服务器发出ajax请求。
browse.js
Template = { setup : function(){ Template.events.csrf(); // etc. etc. }, events: { csrf : 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({ beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } }); }, //etc. etc. } //The actual ajax request Data = { api : { ajax_get_listings : function(cb){ var g, i, o, _ref; _ref = [ $('#ci').val(), $('#co').val(), $('#guests').val()], i = _ref[0], o = _ref[1], g = _ref[2]; if (g) { console.log('getting listings'); return $.ajax({ url:'/api/get_listing_items/', type: 'POST', datatype:'json', data: { available_start_date: i, available_end_date: o, max_guests: g }, success: function(d) { if (d.listings !== null){ Data.listings._results = []; console.log(d); var l = $.parseJSON( $("").html(d.listings).text()); console.log(l); data = l; console.log(data); return cb(data); }else{ $('#ct').text('No listings found for your search criteria. Please keep searching!'); } }, }); } }, }, //etc. etc }
再次,这在Chrome中运行良好。 当我在Firefox上时,它只给了我一个403 Forbidden。 这是追溯:
追溯
头
view source Content-Type text/html Date Mon, 19 Oct 2015 22:06:07 GMT Server WSGIServer/0.1 Python/2.7.3 Vary Cookie X-Frame-Options SAMEORIGIN view source Accept */* Accept-Encoding gzip, deflate Accept-Language en-US,en;q=0.5 Cache-Control no-cache Connection keep-alive Content-Length 54 Content-Type application/x-www-form-urlencoded; charset=UTF-8 Cookie _ga=GA1.1.1619904474.1445292335; _gat=1; TawkConnectionTime=0; __tawkuuid=e||127.0.0.1||mnW1PFpM4y26O8w +2HatshrE3nWV4w3xD7SAtEMYGtV647bMojOwsqzNlPdxYCdB||2; Tawk_560d98fcc096ea637ec4b8c0=vs15.tawk.to:443 ||0 DNT 1 Host 127.0.0.1:8008 Pragma no-cache Referer http://127.0.0.1:8008/properties/ User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0 X-CSRFToken null X-Requested-With XMLHttpRequest
响应
403 Forbidden html * { padding:0; margin:0; } body * { padding:10px 20px; } body * * { padding:0; } body { font:small sans-serif; background:#eee; } body>div { border-bottom:1px solid #ddd; } h1 { font-weight:normal; margin-bottom:.4em; } h1 span { font-size:60%; color:#666; font-weight:normal; } #info { background:#f6f6f6; } #info ul { margin: 0.5em 4em; } #info p, #summary p { padding-top:10px; } #summary { background: #ffc; } #explanation { background:#eee; border-bottom: 0px none; }Forbidden (403)
CSRF verification failed. Request aborted.
You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties.
If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for 'same-origin' requests.
Help
Reason given for failure:
CSRF cookie not set.In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been used correctly. For POST forms, you need to ensure:
- Your browser is accepting cookies.
- The view function uses
RequestContext
for the template, instead ofContext
.- In the template, there is a
{% csrf_token %}
template tag inside each POST form that targets an internal URL.- If you are not using
CsrfViewMiddleware
, then you must usecsrf_protect
on any views that use thecsrf_token
template tag, as well as those that accept the POST data.You're seeing the help section of this page because you have
DEBUG = True
in your Django settings file. Change that toFalse
, and only the initial error message will be displayed.You can customize this page using the CSRF_FAILURE_VIEW setting.
可能有什么不对?
已解决:我把@ensure_csrf_cookie放在获取cookie的视图上(不是ajax请求调用的函数 – 这让我很困惑)。 现在不再在Firefox上使用403了。 好极了
在您的请求标头中,我看到:
X-CSRFToken null
所以我的猜测是在Firefox中设置了cookie。 也许它已经在之前的会话中设置在Chrome中。
Django文档解释了为什么这可能是 :
警告
如果您的视图未呈现包含csrf_token模板标记的模板,则Django可能不会设置CSRF令牌cookie。 这种情况在表单动态添加到页面的情况下很常见。 为了解决这种情况,Django提供了一个视图装饰器来强制设置cookie:ensure_csrf_cookie()。
尝试在views.py中导入
ensure_csrf_cookie
装饰器并使用它包装基本视图。 例如:from django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def base_view(request): # do stuff return render('base.html', {...})
我不确定这是否是根本问题,但我希望这有帮助!