django—csrf中间件
1、作用
1、渲染本网站的前端form表单时,会生成一个字符串来标识该form表单
2、当form表单发起post请求,提交数据时,会携带该参数,后端的csrf中间件就会拿后端保存的字符串进行比对
3、验证通过,代表发起post请求的确实是本网站的前端,否则不是
4、该字符串在前端form表单中,被渲染成一个隐藏的input框
<input type="hidden" name="csrfmiddlewaretoken" value="随机字符串">
2、如何使用
2.1 form表单发起post请求
编写html代码时,只需要在form标签内,使用模板语法{% csrf_token %}
即可,浏览器会自动渲染出一个隐藏的input框
<form action="" method="post">
{% csrf_token %}
<p>username:<input type="text" name="username"></p>
<p>target_account:<input type="text" name="target_user"></p>
<p>money:<input type="text" name="money"></p>
<input type="submit">
</form>
2.2 ajax发起post请求
结合forms表单演示
1、添加键值对到data字典中
<!--form标签-->
{% for transfer in transfer_obj %}
{{ transfer.label }}{{ transfer }}
<span>{{ transfer_obj.errors.0 }}</span>
{% endfor %}
<input type="submit" value="提交" id="d1">
{% csrf_token %}
<!--ajax
方式1:可以通过查找标签获取值的方式添加到data字典中,如username
方式2:针对csrf_token,可以直接使用模板语法{{csrf_token}}
-->
<script>
$('#d1').click(function () {
$.ajax({
url:'',
type:'post',
data:{'username':$('#id_username').val(), 'target_user':$('#id_target_user').val(),
'money':$('#id_money').val(), 'csrfmiddlewaretoken':'{{ csrf_token }}'},
success:function (data) {
alert('提交成功')
}
})
})
</script>
2、利用官网提供的文件
将下面的js文件拷贝到项目的静态文件夹下即可
在html页面通过导入该文件即可自动帮我们解决ajax提交post数据时校验csrf_token的问题,(导入该配置文件之前,需要先导入jQuery,因为这个配置文件内的内容是基于jQuery来实现的)
// setup.js
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);
}
}
});
3、csrf相关的装饰器
需要导入模块
from django.views.decorators.csrf import csrf_exempt,csrf_protect
两种装饰器的区别
@csrf_exempt # 不校验 csrf
def index(request):
return HttpResponse('index')
@csrf_protect # 校验
def login(request):
return HttpResponse('login')
在CBV上的区别
# csrf_exempt
# csrf_exempt这个装饰器只能给dispatch装才能生效
@method_decorator(csrf_exempt,name='dispatch') # csrf_exempt加载类上面,指定dispatch
class MyIndex(views.View):
# @method_decorator(csrf_exempt) # 也可以直接加给dispatch
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return render(request,'transfer.html')
def post(self,request):
return HttpResponse('OK')
"""
csrf_protect方式全都可以 跟你普通的装饰器装饰CBV一致
"""
@method_decorator(csrf_protect,name='post') # 可以
class MyIndex(views.View):
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return render(request,'transfer.html')
def post(self,request):
return HttpResponse('OK')