CSRF与AJAX
1. form表单
在含有POST表单的模板中,需要在其<form>
表单元素内部添加csrf_token
标签,如下所示:
<form action="" method="post"> {% csrf_token %} .... </form>
2. Ajax提交
①在你的前端模版的JavaScript代码处,添加下面的代码:
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) { // 这些HTTP方法不要求CSRF包含 return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });
然后再写ajax表单请求
$.ajax({ url: xx, type: 'POST', data: { }, success: function (res) { } )
② 直接在主界面写{% csrf_token %}, 因为没有form表单,所以写那个位置都行
然后直接data引用
$.ajax({ url: xx, type: 'POST', data: { 'csrfmiddlewaretoken': $("[name='csrfmiddlewaretoken']").val() },
2.装饰器
①单独指定csrf验证需要
有时候,我们在全站上关闭了CSRF功能,但是希望某些视图还有CSRF防御,那怎么办呢?
Django为我们提供了一个csrf_protect(view)
装饰器,使用起来非常方便,如下所示:
from django.views.decorators.csrf import csrf_protect from django.shortcuts import render @csrf_protect def index_view(request): return render(request, "template.html")
②单独指定忽略csrf验证
有正就有反。在全站开启CSRF机制的时候,有些视图我们并不想开启这个功能。比如,有另外一台机器通过requests库,模拟HTTP通信,以POST请求向我们的Django主机服务器发送过来了一段保密数据。它无法携带CSRF令牌,必然会被403。
这怎么办呢?
在接收这个POST请求的视图上为CSRF开道口子,不进行验证。这就需要使用Django为我们提供的csrf_exempt(view)
装饰器了,下面是使用范例:
from django.views.decorators.csrf import csrf_exempt from django.http import HttpResponse @csrf_exempt def index_view(request): return HttpResponse('Hello world')
③确保csrf令牌被设置
Django还提供了一个装饰器,确保被装饰的视图在返回页面时同时将csrf令牌一起返回。
这个装饰器是:ensure_csrf_cookie(view),其使用方法和上面的一样:
from django.views.decorators.csrf import ensure_csrf_cookie from django.http import HttpResponse @ensure_csrf_cookie def index_view(request): return HttpResponse('Hello world')
④requires_csrf_token(view)
这个装饰器类似csrf_protect,一样要进行csrf验证,但是它不会拒绝发送过来的请求。
from django.views.decorators.csrf import requires_csrf_token from django.shortcuts import render @requires_csrf_token def index_view(request): return render(request, "a_template.html", c)