zoukankan      html  css  js  c++  java
  • Django 中间件

    一.中间件

    中间件就是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎使用。

    Django中间件的定义:

    Middleware is a framework of hooks into Django’s request/response processing. 
    It’s a light, low-level “plugin” system for globally altering Django’s input or output.
    

    二.中间件用途

    django的中间件,其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法,所以如果需要修改请求,例如被传送到view中的HttpRequest对象,或者是修改view返回的HttpResponse对象,就可以通过中间件来实现。

    Django默认的中间件:

    在django项目的settings模块中,有一个MIDDLEWARE变量

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    

    请求传递到Django的过程如下:

    三.中间件方法

    中间件的五个方法

    process_request(self,request)
    process_view(self, request, callback, callback_args, callback_kwargs)
    process_template_response(self,request,response)
    process_exception(self, request, exception)
    process_response(self, request, response)
    

    中间件方法的运行流程图:

    四.自定义中间件

    第一步:导入MiddlewareMixin

    from django.utils.deprecation import MiddlewareMixin
    

    第二步:自定义中间件

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse
    
    class MyMiddelware1(MiddlewareMixin):
        def process_request(self, request):
            print('MyMiddelware1=====>request')
    
        def process_response(self, request, response):
            print('MyMiddelware1======>response')
            # 返回response
            return response
    
    
    class MyMiddelware2(MiddlewareMixin):
        def process_request(self, request):
            print('MyMiddelware2=====>request')
    
        def process_response(self, request, response):
            print('MyMiddelware2======>response')
            # 返回response
            return response
    

    第三步:在view中定义一个视图函数

    def index(request):
        print('视图函数')
        return HttpResponse('aaa')
    

    第四步:在settings.py的MIDDLEWARE里注册自己定义的中间件

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'app01.mymiddelware.MyMiddelware1',
        'app01.mymiddelware.MyMiddelware2',
    ]
    

    结果:

    MyMiddelware1=====>request
    MyMiddelware2=====>request
    视图函数
    MyMiddelware2======>response
    MyMiddelware1======>response
    

    注意:如果当请求到达process_request的直接不符合条件返回,程序将把请求直接发给其对应的process_response返回.然后依次返回到请求者,结果如下:

    MyMiddelware1=====>request
    MyMiddelware2=====>request
    MyMiddelware2======>response
    MyMiddelware1======>response
    

    总结:

    1.中间件的preocess_request方法是在执行视图函数之前执行的
    2.当配置多个中间件时,会按照MIDDLEWARE中的注册顺序,也就是列表的索引值,从前到后依次执行的
    3.不同中间件之间传递的request都是同一个对象
    

    process_view

    process_view(self,request,callback, callback_args, callback_kwargs)

    该方法由四个参数:

    • request是HttpResponse对象
    • callback是Django即将使用的视图函数
    • callback_args是将传递给视图的位置参数的列表
    • callback_kwargs是将传递给视图的位置参数的字典

    Django会在调用视图函数之前调用process_view方法

    它应该返回None或一个HttpResponse对象。 如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。 如果它返回一个HttpResponse对象,Django不会调用适当的视图函数。 它将执行中间件的process_response方法并将应用到该HttpResponse并返回结果。

    process_exception

    process_exception(self,request,exception)

    该方法有两个参数:

    • request是HttpResponse对象
    • exception是视图函数异常产生的Exception对象

    这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个None也可以是一个HttpResponse对象。如果是HttpResponse对象,Django将调用模板和中间件中的process_response方法,并返回给浏览器,否则将默认处理异常。如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行。

    process_template_response

    process_template_response(self,request,response)

    该方法对视图函数返回值有要求,必须是一个含有render方法类的对象,才会执行此方法

    五.CSRF_TIKEN跨站请求伪造

    CSRF介绍:

    CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性
    
    可以这样来理解:
           攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。 如下:其中Web A为存在CSRF漏洞的网站,Web B为攻击者构建的恶意网站,User C为Web A网站的合法用户
    

    CSRF攻击防范:

    1.验证HTTP Referer字段
    2.在请求地址中添加token并验证(Django处理方式)
    3.在HTTP头中自定义属性并验证
    

    在form表单中应用:

    <form action="" method="post">
        {% csrf_token %}
        <p>用户名:<input type="text" name="name"></p>
        <p>密码:<input type="text" name="pwd"></p>
        <input type="submit" value="提交">
    </form>
    

    在AJAX中应用

    <script>
        $(".btn").click(function () {
            $.ajax({
                url: '',
                type: 'post',
                data: {
                    'name': $('[name="name"]').val(),
                    'password': $("#pwd").val(),
                    'csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()
                    'csrfmiddlewaretoken':'{{ csrf_token }}'
                },
                success: function (data) {
                    console.log(data)
                }
    
            })
        })
    </script>
    

    在HTTP头中自定义属性并验证,放在cookie中:

    获取cookie:document.cookie

    是一个字符串,可以自己用js切割,也可以用jquery插件

    获取cookie:$cookie('csrftoken')

    设置cookie:$cookie('key','value')

    <script>
        $(".btn").click(function () {
            var token=$.cookie('csrftoken')
            //var token='{{ csrf_token }}'
            $.ajax({
                url: '',
                headers:{'X-CSRFToken':token},
                type: 'post',
                data: {
                    'name': $('[name="name"]').val(),
                    'password': $("#pwd").val(),
                },
                success: function (data) {
                    console.log(data)
                }
    
            })
        })
    </script>
    

    六.局部禁用和使用csrf

    全局禁用:注释掉中间件 'django.middleware.csrf.CsrfViewMiddleware',

    局部禁用:使用装饰器,导入from django.views.decorators.csrf import csrf_exempt,csrf_protect

    在FBV中使用:

    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    # 不再检测,局部禁用(前提是全站使用)
    # @csrf_exempt
    # 检测,局部使用(前提是全站禁用)
    # @csrf_protect
    def csrf_token(request):
        if request.method=='POST':
            print(request.POST)
    
            return HttpResponse('ok')
        return render(request,'csrf_token.html')
    

    在CBV中使用:

    # CBV中使用
    from django.views import View
    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    from django.utils.decorators import method_decorator
    # CBV的csrf装饰器,只能加载类上(指定方法为dispatch)和dispatch方法上(django的bug)
    # 给get方法使用csrf_token检测
    @method_decorator(csrf_exempt,name='dispatch')
    class Foo(View):
        def get(self,request):
            pass
        def post(self,request):
            pass
    
  • 相关阅读:
    Maven3核心技术(笔记三)
    解决Ubuntu下Sublime Text 3无法输入中文
    python3项目之数据可视化
    Python模块Pygame安装
    PHP命名空间(Namespace)
    git的安装使用和代码自动部署
    input:text 的value 和 attribute('value') 不是一回事
    touch事件学习
    获得 选中文字
    linux使用crontab实现PHP执行定时任务及codeiginter参数传递相关
  • 原文地址:https://www.cnblogs.com/louyefeng/p/10008475.html
Copyright © 2011-2022 走看看