djangoCSRF的使用和禁止说明
CSRF简单来说就是为了防止跨站请求伪造,简单来说就是在渲染页面的时候会生成一个随机字符串,那么在有数据返回给服务器的时候,会在对这些数据进行核对,确认是否是来自于页面的请求,如果不是则会返回给出403错误

Django的CSRF原理
django 第一次响应来自某个客户端的请求时(get方式),会在服务器端随机生成一个 token,然后把这个 token 写在用户请求的 cookie 里,同时也会给客户端页面发送一个随机的 token (form表单中以{% csrf_token %}方式获取)用以认证。之后客户端每次以 POST 方式向服务端提交请求时,都会带上这个 token,这样就能避免被 CSRF 攻击。 + 在返回的 HTTP 响应的 cookie 里,django 会为你添加一个 csrftoken 字段,其值为一个自动生成的 token; + 在所有的 POST 表单中,必须包含一个 csrfmiddlewaretoken 字段 (只需要在模板里加一个 tag, django 就会自动帮你生成,见下面) + 在处理 POST 请求之前,django 会验证这个请求的 cookie 里的 csrftoken 字段的值和提交的表单里的 csrfmiddlewaretoken 字段的值是否一样 + 如果一样,则表明这是一个合法的请求,否则,这个请求可能是来自于别人的 csrf 攻击,返回 403 Forbidden. + 在所有 ajax POST 请求里,添加一个 X-CSRFTOKEN header,其值为 cookie 里的 csrftoken 的值
Django的内置CSRF
django为用户实现了防止出现伪造的情况,所以在创建项目后,在settings的中间件里面,django.middleware.csrf.CsrfViewMiddleware则会进行全局的验证。
在日常使用的时候,我们日常在使用的时候只需要在form表单中,加入{% csrf_token %}即可。
# 基本样例
{% for filed in form %}
{% csrf_token %} # 这里加入这句话即可
<h3>{{ filed.label }}</h3>
{{ filed }}
{% endfor %}
Django CSRF的取消
由于前端的需求多样性,我们并非必须要通过form来进行渲染,也可能会通过ajax动态提交,判断&验证等或前后端分离,设计多个不同的前端等,这个时候带csrf就比较麻烦,最简单的做法就是取消了。一般来说如果只是极个别情况,建议可以采用
局部取消,如果整站大部分都涉及这种分离模式,那就可以直接取消中间件。
全站禁用
这个比较简单,只要在settings里面,将中间件这行直接注释了即可。
局部禁用
在FBV模式里面,只需要禁用的view函数中,引入from django.views.decorators.csrf import csrf_exempt,csrf_protect这2个装饰器。
@csrf_protect #全站不用,某个函数需要使用认证的时候
还有一个就是 @csrf_exempt @全站使用,某个不需要的可以忽略
在CBV模式里面,只能在类里面加上装饰器,因此可以用以下方法
#自定义的装饰器
def wrapper(func):
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
# 1. 指定方法上添加装饰器
from django.utils.decorators import method_decorator
class Foo(View):
@method_decorator(wrapper) #先导入方法,然后装饰器以参数的形式添加
def get(self,request):
pass
def post(self,request):
pass
# 2. 在类上添加
@method_decorator(wrapper,name='dispatch')
class Foo(View):
def get(self,request):
pass
def post(self,request):
pass
Ajax提交
在使用Ajax提交数据的时候,希望也可以携带csrf认证,可以以post的方式提交,放在data中携带
<form method="POST" action="/csrf1.html">
{% csrf_token %}
<input id="user" type="text" name="user" />
<input type="submit" value="提交"/>
<a onclick="submitForm();">Ajax提交</a>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script>
function submitForm(){
var csrf = $('input[name="csrfmiddlewaretoken"]').val();
var user = $('#user').val();
$.ajax({
url: '/csrf1.html',
type: 'POST',
data: { "user":user,'csrfmiddlewaretoken': csrf},
#注意csrf随机字符串,后台有固定的名字接收,这种方式是通过标签获取的对应值 success:function(arg){
console.log(arg);
}
})
}
<form method="POST" action="/csrf1.html">
{% csrf_token %}
<input id="user" type="text" name="user" />
<input type="submit" value="提交"/>
<a onclick="submitForm();">Ajax提交</a>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
function submitForm(){
var token = $.cookie('csrftoken');
var user = $('#user').val();
$.ajax({
url: '/csrf1.html',
type: 'POST',
headers:{'X-CSRFToken': token}, #注意csrf随机字符串后台有固定的名字接收
data: { "user":user},
success:function(arg){
console.log(arg);
}
})
}
</script>
注意一定注意:ajax POST提交的时候,csrf-token 随机字符串 直接放在data数据中的方式为:data:{csrfmiddlewaretoken:"{{ csrf_token }}"} 若是导入自己写的JS文件,那上述方法就不能获取到Django后台发送的随机字符串,而是需要利用上面介绍的两种方式获取(页面写上{% csrf_token %},通过隐藏的input标签取value值写在POST 提交的data数据中;或是从cookie中获取,写在头文件中。)
使用django框架时: + 每次初始化一个项目时都要看看 django.middleware.csrf.CsrfViewMiddleware 这个中间件 + 每次在模板里写 form 时都需要加一个 {% csrf_token %} tag + 每次发 ajax POST 请求,都需要加一个 X_CSRFTOKEN 的 head