正在进入ing...

djangoCSRF的使用和禁止说明

发布时间:2020-09-16 浏览量: 952 文章分类: python

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

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