一、前言
之前我们写代码,都是会把settings配置文件里面的csrf的中间注释掉,不然我们请求post时候的会出现403 forbidden,那这个到底有啥用呐?它的原理又是什么呐?
csrf原理:
我们向服务请求时,服务器认为你是get请求的,服务器不仅把数据给你,还偷偷的的给你一大堆字符串,这个字符串是加密的,但是只有我服务器自己能反解,你客户端下一次提交数据的时候,需要带上这个字符串来再来,这样的话我服务器才会允许,不然的话,不允许你提交数据。
原理图:
二、From表单提交方式
2.1、前提条件
说明:因为我们之前都是注释掉django中的settings文件中的csrf插件,我们现在不用注释掉
'django.middleware.csrf.CsrfViewMiddleware' #全局中间件
2.2、templates中login.html的改进
说明:在输入框之前加上{% csrf_token %},表示这边加上一个隐藏的input框,这个input框默认值是csrf_token值,提交的发送给后端
如图:
确实会在添加一个隐藏的input的框,这个input乱的value是csrf_token的值。
2.3、get请求成cookie
说明:当我get请求的时候,我会自动在我的浏览器cookie生成一个值,然后相应的时候,服务器会返回这个cookie的值
所以,在input框之前添加{% csrf_toke %}的时候,不仅在form中生产一个隐藏的input框,而且请求get的时候,在本地cookie也会生产csrf的值,当然如果你在前端指向获取csfr_token的值,你就直接在前端获取就行了:
{ { csrf_token }}
三、ajax提交
我们之前说了,当我们需要用post提交的时候,我们需要带这个csrf_token去后台去跟服务器去校验,那我们怎么带这个这个csrf_token值呐,其实我们在请求的时候,把它放在header里面,发送给服务器就可以了。
3.1、ajax执行前置条件
说明:就是说对整个页面的ajax的做一个配置,如果是整体的ajax都要统一的加一个header,或者说统一的都是用post的请求方式,因为发送ajax之前都会执行以下这个函数,那么就可以用如下方式:
$.ajaxSetup({ beforeSend:function(xhr,settings){ xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken')); //xhr 表示是XMLHTTPResquest的一个对象,因为ajax的发送底层原理就是用这个的 //obj=XMLHTTPReuquest() //obj.open() //obj.send() //settings是下面的ajax的配置,比如settings.type,settings.url,settings.data等等 } });
3.2、ajax的请求方式
说明:所以我们就用完整的ajax请求一次
1 29 10 11 35
3.3、排除post请求
说明:如果我的ajax里面不是post请求是get请求的话,那咋办,它也会照样需要发送csrf_token,但是我们只想用post请求的时候,去校验这个csrf_token值:
function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); }
所以我们完整的test.html编写如下:
1 2 3 4 56 7 8 {% csrf_token %} 9 10 11 12 13 14 41 42
更多:https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
三、跨站请求伪造
django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。
3.1、全局
中间件 django.middleware.csrf.CsrfViewMiddleware
3.2、局部
说明:如果你100个函数,只有两个不用,那么就不用注释掉全局的,用csrf_exempt,如果说100个函数只用两个需要认证,就需要注释掉全局的,然后用csrf_protect。
局部:
- @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
- @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
使用前提:from django.views.decorators.csrf import csrf_exempt,csrf_protect
3.3、具体使用如下:
from django.views.decorators.csrf import csrf_exempt,csrf_protect #这边需要导入这两个模块@csrf_exempt #不需要认证def index(request): if request.session.get("is_login",None): return render(request,'index.html') else: return HttpResponse('gun')