一、简介
django为用户实现防止跨站请求伪造的功能,通过中间件django.middleware.csrf.CsrfViewMiddleware
来完成。
当用post提交数据的时候,django会去检查是否有一个csrf的随机字符串,如果没有就会报错
1.客户端在非Django返回页面上发送post请求时,会被Django拦截,但非服务器报错
2.客户端在Django返回页面上发送post请求时,需要加上{% csrf_token %}方能发送成功
因为在之前访问服务器后,服务器发送一段字符串
第二次post请求访问需要加上{% csrf_token %}带着这个字符串认证
除此之外,还有另一种cookie认证方式,后面有讲到。
而对于django中设置防跨站请求伪造功能有分为全局和局部。
全局:
中间件 django.middleware.csrf.CsrfViewMiddleware
局部:
@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
注:from django.views.decorators.csrf import csrf_exempt,csrf_protect
二,简单原理(个人见解,欢迎指正)
每个Django服务端settings.py源码里都有一个:
SECRET_KEY = '^!9td%%@mim%&xhfirgwivgxk!qt3dwg6vo=m*@37nkzw5uspk'
这个就是密匙,用来进行验证
首先第一次访问服务器,服务器会把密匙发给客户端(当然客户端是看不见的),客户端拿到密匙,拼接上当前客户端时间,进行md5(也可能其他的)加密,然后把这个加密信息和之前的当前客户端时间发到后台之后,后台拿到客户端当前时间和密匙也进行MD5加密,然后比较两次结果,一样则认为没有问题
所以要通过验证需要两点:
1.拿到密匙
2.根据规则加密(自动的)
3.发过去MD5加密结果(时间会自动发)
有的还加上了有效时间限制和有效时间内的次数限制(第二次相同的无效)
三、应用
1、普通表单
veiw中设置返回值:
return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))
或者
return render(request, 'xxx.html', data)
html中设置Token:
{% csrf_token %}
#在页面自动加上一个隐藏的input标签,不依赖form表单而存在
#<input type="hidden" name="csrfmiddlewaretoken" value="Hx9OMDpLJFsG8P7Sy6gGGh5FGXmBXywQV5JQhDPmi7HFmsDh08GILYRPNEwvGouF">
2.Ajax
对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。
第一种方式 :直接在hide标签中获取到data里并提交
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{#<form action="/ajax/" method="post">#}
{% csrf_token %}//不依赖form表单而存在
{# <input type="submit">form提交#}
{#</form>#}
<script src="/static/jquery-3.3.1/jquery-3.3.1.js"></script>
<button id="q">提交</button>
<script>
$("#q").click(function () {
var csrf=$('input[name="csrfmiddlewaretoken"]').val();//拿到csrf的字符串
$.ajax({
url:"/ajax/",
type:"POST",
data:{"k1":"123","csrfmiddlewaretoken":csrf},
//data:{"k1":"123","csrfmiddlewaretoken":{{csrf_token}},},不用获取
success:function (arg) {
console.log(arg)
}
})
})
</script>
</body>
</html>
第二种方式 : 获取本地cookie相关信息,放在请求头中发送 两种方式,获取值不同
document.cookie
能获取到本地Cookie(字符串形式),如下:
“csrftoken=CibmiHzG0mFPA7EqubC0I6jqRCBJjvKbQQLoNHZhzOUOOKaPWd22NN5AYjLD2lI0”
<script src="/static/jquery-3.3.1/jquery-3.3.1.js"></script>
<script src="/static/carhartl-jquery-cookie-92b7715/jquery.cookie.js"></script>
<button id="q">提交</button>
<script>
$("#q").click(function () {//第二种方式
var token = $.cookie('csrftoken');
$.ajax({
url:"/ajax/",
type:"POST",
headers:{"X-CSRFToken":token},
data:{"k1":"123",},
success:function (arg) {
console.log(arg)
}
})
})
</script>