Django—中间件详解

Django—中间件

  1. 中间件的定义

    • 定义:中间件是django请求/响应处理的钩子框架,它是一个轻量级的、低级的插件系统,用于全局改变django的输入或输出
    • 中间件以类的形式体现
    • 每个中间件组件负责一些特定的功能,例如:django包含一个中间件组件AuthenticationMiddleware,她使用会话将用户与请求关联起来
  2. 中间件使用

    • 编写中间件:

      • 中间件类必须继承自django.utils.deprecation.MiddlewareMixin
      • 中间件类必须实现下列五个方法中的一个或多个
        • process_request(self,request)
          • 作用:执行主路由之前被掉用,在每个请求上调用,返回None(请求通过)或者HttpResponse对象(请求不通过)
          • 用途:过滤请求
        • process_view(self,request,callback,callback_args,callback_kwargs):
          • 作用:callback:为视图函数;callback_args:视图函数的位置参数,callback_kwargs:视图函数的关键字参数;调用视图之前被调用,在每个请求上调用,返回None(请求通过)或者HttpResponse对象(请求不通过)
          • 用途:用于代码层面的替换和过滤,这个方法可以拿到视图函数的参数
        • process_response(self,request,response)
          • 作用:response:即是视图函数的响应对象;在所有响应返回浏览器之前被调用,在每个请求上调用,返回HttpResponse对象
        • process_exception(self,request,exception)
          • 作用:处理过程中抛出异常时被调用,返回一个HttpResponse对象
          • 用途:用于一般用于捕获发生的异常,并将其邮件发送给开发人员
        • process_template_response(self,request,response)
          • 作用:在视图函数执行完毕,且视图函数返回的对象中包含render方法时被调用;该方法需要返回实现了render方法的响应对象
      • 注:中间件中的大多数方法在返回None时表示忽略当前操作进入下一项事件,当返回HttpResponse对象时,表示此请求结束,直接返回给客户端
    • 注册中间件:

      • 在settings.py文件中进行注册

        # file:settings.py
        MIDDLEWARE= [
        ···
        'MyMiddleWare',
        ]
        
      • 注意:配置为列表形式,中间件被调用时,在请求视图被处理前,中间件由上至下依次执行;在请求视图被处理后,中间件由下至上依次执行

    • 示例:

      • 添加过滤请求次数中间件

        # file:mymiddleware.py
        from django.http import HttpResponse
        from django.utils.deprecation import MiddlewareMixin
        import re
        class MWare(MiddlewareMixin):
           count_dict = {} #创建用于统计次数的字典
           def process_request(self,request):
              request_ip = request.META['REMOTE_ADDR'] #获取请求IP
              request_url = request.path_info #获取请求URL
              if re.match(r'^/test',request_url): #匹配请求是否以/test开头
                    times = self.count_dict.get(request_ip,0) #查询当前IP的请求次数,默认为0
                    self.count_dict[request_ip]= times + 1 #请求次数 + 1
                    if times < 5: #如果请求次数<5次,请求正常通过
                       return
                    else: #如果请求次数>5次,则返回HttpResponse,阻止请求
                       return HttpResponse("访问次数超过5次,请求失败")
              else: #如果不是以/test开头则直接正常通过
                    return
        
      • 注册中间件

        # file:settings.py
        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',
           'middleware.mymiddleware.MWare',
        ]
        
    • 附django请求流程图
      django请求流程图

  3. CSRF - 跨站伪造请求攻击

    • 定义:某些恶意网站上包含链接、表单按钮或者JavaScript,它们会利用登陆过的用户在浏览器中的认证信息试图在你的网站上完成某些操作,这就是跨站请求伪造(CSRF:Cross-Site-Request-Forgey)
    • CSRF 防范:
      • django采用比对 ‘暗号’ 机制防范攻击

      • 原理:

        • Cookies中存储暗号1,模板中表单里藏着暗号2,用户只有在本网站下提交数据,暗号2 才会随着表单提交给服务器,django对比两个暗号,对比成功,则认为时合法请求,否则是违法请求 - 403响应码
      • 配置步骤:

        1. 在settings.py文件中确认MIDDLEWARE中django.middleware.csrf.CsrfViewMiddleware是否打开

        2. 在模板中的form标签下添加如下标签{% csrf_token %}

        3. 示例:

          DOCTYPE html>
          <html lang="en">
          <head>
             <meta charset="UTF-8">
             <title>CSRF-TEXTtitle>
          head>
          <body>
          <form action="/test_csrf" method="post">
             {% csrf_token %}
             <input type="text" name="test">
             <input type="submit" value="提交" name="key">
          form>
          body>
          html>
          
      • 特殊说明(局部开放csrf):

        • 如果某个视图不需要django进行csrf保护,可以用装饰器关闭对此视图的检查

        • 样例:

          from django.views.decorators.csrf import csrf_exempt
          @csrf_exempt #使用装饰器关闭csrf对此试图的检查
          def my_view(request):
             return HttpResponse('hello world')
          

你可能感兴趣的:(Django,django,python)