第七章、中间件续写

目录

  • 第七章、中间件续写

    • 一、中间件的执行顺序

      • 测试思路:
      • 自定义中间件
      • 代码
    • 二、跨站请求伪造
    • 三、csrf装饰器
    • 四、post请求提交数据通过 csrf 校验
    • 五、自我拷问
      • 分FBV和CBV
      • 未注释掉 csrf 中间件时 单功能取消 csrf 校验:csrf_exempt
      • 注释掉 csrf 中间件时 单功能开启 csrf 校验:csrf_protect

第七章、中间件续写

一、中间件的执行顺序

测试思路:

  • 在 settings.py 里注册不同中间件,探究默认的执行顺序
  • 在不同中间件的 process_request 和 process_response 等方法中 return HttpResponse 对象会对执行顺序造成什么影响
  • 了解五种方法的触发时机

自定义中间件

  1. 新建一个文件夹(放在全局或 app 内)
  2. 写一个类继承 MiddlewareMiXin 类
  3. 里面书写需要的(五个方法中的某些)方法
  4. 一定要在 settings.py 里配置中间件注册

代码

mymiddleware/mdd.py 自定义中间件

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class MyMdd(MiddlewareMixin):
def process_request(self, request):
print(‘我是第一个中间件里面的process_request方法‘)
def process_response(self, request, response):
print(‘我是第一个中间件里面的process_response方法‘)
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print(view_func)
print(view_args)
print(view_kwargs)
print(‘我是第一个中间件里面的process_view方法‘)
def process_exception(self, request, exception):
print(‘我是第一个中间件里面的process_exception‘)
def process_template_response(self, request, response):
print(‘我是第一个中间件里面的process_template_response‘)
return response
class MyMdd1(MiddlewareMixin):
def process_request(self, request):
print(‘我是第二个中间件里面的process_request方法‘)
def process_response(self, request, response):
print(‘我是第二个中间件里面的process_response方法‘)
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print(view_func)
print(view_args)
print(view_kwargs)
print(‘我是第二个中间件里面的process_view方法‘)
def process_exception(self, request, exception):
print(‘我是第二个中间件里面的process_exception‘)
def process_template_response(self, request, response):
print(‘我是第二个中间件里面的process_template_response‘)
return response
class MyMdd2(MiddlewareMixin):
def process_request(self, request):
print(‘我是第三个中间件里面的process_request方法‘)
def process_response(self, request, response):
print(‘我是第三个中间件里面的process_response方法‘)
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print(view_func)
print(view_args)
print(view_kwargs)
print(‘我是第三个中间件里面的process_view方法‘)
def process_exception(self, request, exception):
print(‘我是第三个中间件里面的process_exception‘)
def process_template_response(self, request, response):
print(‘我是第三个中间件里面的process_template_response‘)
return response

在 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‘,
‘mymiddleware.mdd.MyMdd‘, # 配置上
‘mymiddleware.mdd.MyMdd1‘, # 配置上
‘mymiddleware.mdd.MyMdd2‘, # 配置上]

我们可以总结一下:

process_request

请求来的时候会依次执行 settings.py 配置文件中注册了的中间件里的该方法

  • 如果没有该方法则直接跳过,走下一个中间件
  • 如果该方法里返回了 HttpResponse 对象,那么会直接从当前中间件的 process_response 方法 从下往上依次执行返回,不会再接着往下执行
  • 执行顺序:从上往下
  • 该方法可以实现对用户身份的校验,访问频率的限制,用户权限的校验...

process_response

响应走的时候会依次执行 settings.py 配置文件中注册了的中间件里的该方法(必须将 response 形参返回,因为这个 response 指代的就是返回给前端的数据)

  • 如果没有该方法则直接跳过,走下一个中间件
  • 执行顺序:从下往上
  • 该方法可以帮你实现缓存机制(减缓服务器、数据库的压力)

process_view

路由匹配成功 执行视图函数之前 自动触发(从上往下依次执行)

process_exception

视图函数报错了,自动触发(从下往上依次执行)

process_template_response

视图函数返回的 HttpResponse 对象中包含了 render 属性时会触发,或者是表明一个对象时 TemplateResponse 对象或等价方法 的时候也会触发(从下往上依次执行)

def index(request):
    print("我是 index 视图函数")
    def render():
        return HttpRespone('用户最终能够看到的结果')  # ******
    obj = HttpResponse('index')
    obj.render = render  # 返回的 HttpResponse 对象中必须包含 render 属性,才能触发中间件里定义的 process_template_response 方法
    return obj

强调:在写中间件的时候,只要形参中有 response ,就要记得将其返回,这个Response 是要给前端的信息

二、跨站请求伪造

顾名思义:可以做出钓鱼网站这种的
就类似于你搭建了一个跟银行一模一样的web页面
用户在你的网站转账的时候输入用户名 密码 对方账户
银行里面的钱确实少了 但是发现收款人变了

到底咋回事呢?

你写的form表单中 用户的用户名  密码都会真实的提交给银行后台
但是收款人的账户却不是用户填的 你暴露给用户的是一个没有name属性的input框
你自己提前写好了一个隐藏的带有name和value的input框

解决钓鱼网站的策略


    只要是用户想要提交post请求的页面 我在返回给用户的时候就提前设置好一个随机字符串
    当用户提交post请求的时候  我会自动先取查找是否有该随机字符串
    如果有 正常提交
    如果没有  直接报403 

三、csrf装饰器

from django.views.decorators.csrf import csrf_exempt,csrf_protect,ensure_csrf_cookie

csrf_exempt   # 某个视图不需要进行csrf校验

csrf_protect  # 某个视图需要进行csrf校验

ensure_csrf_cookie  # 确保生成csrf的cookie
  1. csrf_exempt

    只有两种装饰的方式:

    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    from django.utils.decorators import method_decorator
    
    # 第一种
    @method_decorator(csrf_exempt, name='dispatch')
    class MyCsrf(View):
    
        # 第二种
        @method_decorator(csrf_exempt)
        def dispatch(self, request, *args, **kwargs):
            return super().dispatch(request,*args,**kwargs)
        def get(self,request):
            return HttpResponse('hahaha')
  2. csrf_protect

    除了csrf_exempt之外,所有的其他装饰器在CBV上面都有三种方式:

    @method_decorator(csrf_protect,name='post')
    class MyCsrf(View):
        @method_decorator(csrf_protect)
        def dispatch(self, request, *args, **kwargs):
            return super().dispatch(request,*args,**kwargs)
        def get(self,request):
            return HttpResponse('hahaha')
    
        @method_decorator(csrf_protect)
        def post(self,request):
            return HttpResponse('post')
  3. ensure_csrf_cookie

    这个是我的知识盲区 后续再补

四、post请求提交数据通过 csrf 校验

目前所学的拥有post请求的方法有form表单和ajax发送

form表单

你在写的时候只需要加上一个
            {% csrf_token %}

ajax发送有三种

第一种  自己再页面上先通过{% csrf_token %}获取到随机字符串  然后利用标签查找
data:{'username':'jason','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()},
第二种
data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},
第三种
sataic文件夹 再创建一个js文件 拷贝代码

下面给出第三种的js代码

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie('csrftoken');

function csrfSafeMethod(method) {
  // these HTTP methods do not require CSRF protection
  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

$.ajaxSetup({
  beforeSend: function (xhr, settings) {
    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader("X-CSRFToken", csrftoken);
    }
  }
});

然后在html文件上加这一行就好了

{#<script src="/static/setup.js"></script>#}

这样就不需要 在 html 中写 {% csrf_token %} 或在 ajax 中写 {{ csrf_token }}

五、自我拷问

  • 当你网站全局都需要校验 csrf 的时候(未注释掉 csrf 中间件时),有几个不需要校验该如何处理? @csrf_exempt
  • 当你的网站全局不校验 csrf 的时候(注释掉 csrf 中间件时),有几个需要校验该如何处理 ?@csrf_protect

分FBV和CBV

未注释掉 csrf 中间件时 单功能取消 csrf 校验:csrf_exempt

FBV怎么写?

from django.views.decorators.csrf import csrf_exempt

# 全局开启时,局部禁用
@csrf_exempt
def index(request):
  pass

CBV怎么写?

有两种方式,不能针对单个方法,是针对全局的

# CBV比较特殊,不能单独加在某个方法上
# 只能加在类上或dispatch方法上
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt

# @method_decorator(csrf_exempt,name='dispatch')  # 第一种
class Csrf_Token(View):
    @method_decorator(csrf_exempt)  # 第二种
    def dispatch(self,request,*args,**kwargs):
        res = super().dispatch(request,*args,**kwargs)
        return res
      # @method_decorator(csrf_exempt)  # 这里这么写不行!!!
    def get(self,request):
            pass
    def post(self,request):
            pass

注释掉 csrf 中间件时 单功能开启 csrf 校验:csrf_protect

FBV怎么写?

from django.views.decorators.csrf import csrf_protect

@csrf_protect
def lll(request):
    return HttpResponse('lll')

CBV怎么写?

from django.views.decorators.csrf import csrf_protect

from django.views import View
from django.utils.decorators import method_decorator

# 第一种方式
# @method_decorator(csrf_protect,name='post')  # 有效的
class MyView(View):
    @method_decorator(csrf_protect)  # 第三种方式
    def dispatch(self, request, *args, **kwargs):
        res = super().dispatch(request, *args, **kwargs)
        return res

    def get(self, request):
        return HttpResponse('get')

    # 第二种方式
    # @method_decorator(csrf_protect)  # 有效的
    def post(self, request):
        return HttpResponse('post')

原文借鉴了https://www.cnblogs.com/suwanbin/p/11591887.html

在这里感谢!

原文地址:https://www.cnblogs.com/demiao/p/11768709.html

时间: 2024-08-25 10:44:58

第七章、中间件续写的相关文章

Netty源码分析第7章(编码器和写数据)----&gt;第3节: 写buffer队列

Netty源码分析七章: 编码器和写数据 第三节: 写buffer队列 之前的小结我们介绍过, writeAndFlush方法其实最终会调用write和flush方法 write方法最终会传递到head节点, 调用HeadContext的write方法: public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { unsafe.write(msg, prom

Netty源码分析第7章(编码器和写数据)----&gt;第4节: 刷新buffer队列

Netty源码分析第七章: 编码器和写数据 第四节: 刷新buffer队列 上一小节学习了writeAndFlush的write方法, 这一小节我们剖析flush方法 通过前面的学习我们知道, flush方法通过事件传递, 最终会传递到HeadContext的flush方法: public void flush(ChannelHandlerContext ctx) throws Exception { unsafe.flush(); } 这里最终会调用AbstractUnsafe的flush方法

第七章、中间件

目录 第七章.中间件 一.什么是中间件 二.中间件可以做什么 三.再回顾一下django请求生命周期 四.五个可以自定义的方法 第七章.中间件 一.什么是中间件 django 中间件 就类似于是 django 的门户,请求来的时候需要先经过 中间件 才能到达 django 后端(urls),响应走的时候也需要经过 中间件 才能到达 web服务网关接口(wsgif 模块) 二.中间件可以做什么 用户访问频率限制 用户是否是黑名单 白名单 所有用户登录校验 只要是涉及到网址全局的功能 你就应该考虑使

第七章

第七章 控制发光二极管. 尽管linux 驱动直接和硬件打交道,但并不是linux驱动直接向硬件中的内存写数据,而是与本机的i/o内存进行交互.所谓I/O内存是通过各种接口(PCI, USB.蓝牙以太网等)连接到主机的硬件在主机的内存映射.Linux内核提供了多个与I/O内存交互的函数.Linux内核的内存管理模块负责同步I/O内存与硬件的数据. 每一个连接Linux 的硬件在I/O内存中都会有映射首地址.在使用ioread 32.ioread32等函数读写I/O内存时需要指定这些首地址.Led

Android开发艺术探索——第七章:Android动画深入分析

Android开发艺术探索--第七章:Android动画深入分析 Android的动画可以分成三种,view动画,帧动画,还有属性动画,其实帧动画也是属于view动画的一种,,只不过他和传统的平移之类的动画不太一样的是表现形式上有点不一样,view动画是通过对场景的不断图像交换而产生的动画效果,而帧动画就是播放一大段图片,很显然,图片多了会OOM,属性动画通过动态的改变对象的属性达到动画效果,也是api11的新特性,在低版本无法使用属性动画,但是我们依旧有一些兼容库,OK,我们还是继续来看下详细

ROS机器人程序设计(原书第2版)补充资料 (柒) 第七章 3D建模与仿真 urdf Gazebo V-Rep Webots Morse

ROS机器人程序设计(原书第2版)补充资料 (柒) 第七章 3D建模与仿真 urdf Gazebo V-Rep Webots Morse 书中,大部分出现hydro的地方,直接替换为indigo或jade或kinetic,即可在对应版本中使用. 提供ROS接口的3D软件比较多,本章以最典型的Gazebo介绍为主,从Player/Stage/Gazebo发展而来,现在独立的机器人仿真开发环境,目前2016年最新版本Gazebo7.1配合ROS(kinetic)使用. 补充内容:http://blo

CSS3秘笈:第七章

第七章  margin.padding和border 1.盒模型:四个属性: (1)padding:内容与其边框线之间的空间. (2)border:盒子周围的直线 (3)background-color:用来填充边框内部空间的,包括padding区域. (4)margin:一个标签和另一个标签之间的间隔. 2.padding和margin的区别:padding是在内容和边框之间增加空间.避免内容被硬塞在方框里面,它还包括背景区域,因此padding占用的空间也可以为空白的内容.而margin则是

JavaScript DOM编程艺术-学习笔记(第七章)

第七章: 1.dom方法创建并且插入标签:(这种方法并没有改变文档的物理内容,而是在改变dom树) ①创建元素节点:createElement(); ②内部前插入:appendChild() ③创建文本节点:createTextNode(); ④设置属性节点:setAttribute(); ⑤外部前插入:父元素.insertBefore(插入的元素,目标元素);                  插入的元素被插入到,目标元素的前面. ⑥没有inserAfter()函数. 2.小知识点:①appe

第七章随笔

第七章:      1.尽管linux驱动直接与硬件打交道,但并不是linux驱动直接向硬件中的内存写数据,而是本机的I/O内存进行交互. linux驱动           I/O内存             硬件      2.linux内核的内存管理模块负责同步I/O内存和硬件中的数据.每一个连接linux的硬件在linux内存中都有映射首地址,在使用ioread.iowrite等函数读写I/O内存时,指定这些首地址.      3.硬件在被检查到只说明在内核空间中建立了I/O内存,要想在