本文介绍: 中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能中间件流程图如何自定义中间件1.创建存储自定义中间件代码的py文件或者目录(如果中间件很多)2.参考自带中间件的代码编写类并继承3.在类中编写五个可以自定义的方法4.一定在配置文件注册中间件可以生效编写自定义中间件(在mymiddlie中编写MyMiddleware001)

一、中间件的介绍

中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能

中间件流程图
在这里插入图片描述

中间件有什么用

如果你想修改请求,例如被传送到view中的HttpRequest对象。 或者你想修改view返回的HttpResponse对象,这些都可以通过中间件来实现

可能你还想在view执行之前做一些操作,这种情况就可以用 middleware实现

Django默认的中间件:(在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下图)

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',
]

这七个中间件程序会在请求来时自上而下依次的处理request请求,在响应走时自下而上依次处理response响应

中间件功能

网站访问频率的校验 用户权限的校验等全局类型的功能需求

前期我们要访问post请求,中间件的第四个字符串妨碍了简单post请求,初期阶段我们将其注释掉了

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',
]

这七个字符串实际上对应的是中间件程序存储路径
在这里插入图片描述
我们顺着路径文件,点进去可知源码
在这里插入图片描述
由上述图可知

1.七个中间件都继承了MiddlewareMixin类
2.都几乎有process_request和process_response函数
3.都必须传入参数
process_request需要传入request参数;
process_response需要传入request和response两个参数,必须返回response。

自定义中间

如何自定义中间件
1.创建存储自定义中间件代码的py文件或者目录(如果中间件很多)
2.参考自带中间件的代码编写类并继承
3.在类中编写五个可以自定义的方法
4.一定在配置文件注册中间件才可以生效
在这里插入图片描述
编写自定义的中间件(在mymiddlie中编写MyMiddleware001)
在这里插入图片描述
编写好中间件,一定要去settings里的Middleware中注册自定义的中间件
在这里插入图片描述

中间件的顺序

我们只是定义了process_reqtest和process_response函数,我们想看看执行的顺序的,我们可以做一个小测试

mymiddle.py(自定义的中间件)

from django.utils.deprecation import MiddlewareMixin

class MyMiddleware001(MiddlewareMixin):
    def process_request(self,request):
        print('from MyMiddleware001 process_request')

    def process_response(self,request,response):
        print('from MyMiddleware001 process_response')
        return response

class MyMiddleware002(MiddlewareMixin):
    def process_request(self,request):
        print('from MyMiddleware002 process_request')

    def process_response(self,request,response):
        print('from MyMiddleware002 process_response')
        return response

当我们从网页向URL发送请求时,请求通过了网关接口到达了中间件,在中间件的执行过程是自上而下,从而经过路由层>>视图层>>>等,当响应是经过中间件的时候是自下而上的,返回给网关接口,再打包浏览器

在这里插入图片描述
打印结果
在这里插入图片描述
如果我们还想测试如果遇到HttpResponse对象,会怎么样?看下面的解释

django中间件两个基本方法
process_request
1.请求来的时候会从上往下依次经过每一个注册的中间件里面的该方法 如果没有则直接跳过
2.如果该方法自己返回了HttpResponse对象那么不再往后执行而是直接原路返回

如果请求遇到了process_request方法,该方法返回了HttpResponse对象,如下

class MyMiddleware001(MiddlewareMixin):
    def process_request(self,request):
        print('from MyMiddleware001 process_request')
        return HttpResponse('你没有权限执行下面的中间件')  # 遇到了HttpResponse对象

    def process_response(self,request,response):
        print('from MyMiddleware001 process_response')
        return response

他经过的行径如黄色箭头,请求通过网关到中间件自上而下到达了中间件MyMiddleware001,就会直接执行MyMiddleware001的process_response方法,直接原路返回,不会走下面的中间件MyMiddleware002。

在这里插入图片描述
process_response

1.响应走的时候会从下往上依次经过每一个注册了的中间件里面的该方法 如果没有则直接跳过
2.该方法有两个先request和response 形参response指代的就是后端想要返回给前端浏览器的数据 该方法必须返回该形参 也可以替换

from django.utils.deprecation import MiddlewareMixin
from django.http import HttpResponse
class MyMiddleware001(MiddlewareMixin):
    def process_request(self,request):
        print('from MyMiddleware001 process_request')

    def process_response(self,request,response):
        print('from MyMiddleware001 process_response')
         # return response
		return HttpResponse('中间1直接返回了,返回了response')

注意:
1.一个请求经过了中间件,如果在执行process_request方法的时候直接返回了HttpResponse对象那么会原路返回执行自定义中间件的process_response 不是执行所有。

​ 2.在flask中,是从最底层中间程序响应函数开始执行的

django中间件三个了解得方法

1.process_view
	路由匹配成功之后执行视图函数/类之前自动触发(顺序同process_request)
2.process_exception
	视图函数/类执行报错自动触发(顺序同process_response)
3.process_template_response
	视图函数/类返回的HttpResponse对象含有render并且对应一个方法的时候自动触发(顺序同process_response)

csrf跨站请求伪造

钓鱼网站:攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号添加统管理员,甚至于购买商品、虚拟货币转账等。 如下:其中Web A为存在CSRF漏洞的网站,Web B为攻击者构建的恶意网站,User C为Web A网站的合法用户
举例:英语四六级考试需要网上缴费,你交钱了,但是你会发现卡里的钱扣了但是却交到了一个莫名的账户,并不是四六级官方账户

攻击原理:

在这里插入图片描述

模拟一个钓鱼网站案例

做两个相同的页面,一个真网站一个假网站,其中假网站隐藏一个标签

views.py

def transfer_func(request):
    if request.method == "POST":
        username = request.POST.get('username')
        target_name = request.POST.get('target_name')
        money = request.POST.get('money')
        print(f'{username}{target_name}转了{money}元')
    return render(request,'transfer_func.html')

真网站 tansfer_func.html

<h1>我是真网站</h1>
<form action="" method="post">
    <p>username <input type="text" name="username"></p>

    <p>target_name <input type="text" name="target_name"></p>

    <p>money <input type="number" name="money"></p>

    <p><input type="submit"></p>
</form>

假网站 tansfer_func.html

<h1>我是假网站</h1>
<form action="http://127.0.0.1:8000/transfer/" method="post">
    <p>username <input type="text" name="username" style="display: none" value="我是假网站">
        <input type="text">
    </p>
    <p>target_name <input type="text" name="target_name"></p>
    <p>money <input type="number" name="money"></p>
    <p><input type="submit"></p>
</form>

现在我通过假网站模拟转账,就会从真网站请求信息,这是后我们真网站会接受到数据
在这里插入图片描述
思考如何区分真假网站页面发送的请求

csrf校验策略

在这里插入图片描述

1. form表单里加一个唯一标识来验证

在这里插入图片描述

2. ajax验证方法,有三种验证方法

1.手动获取input,方法比较麻烦

<form action="" method="post">
    {% csrf_token %}
    <p>username <input type="text" name="username"></p>

    <p>target_name <input type="text" name="target_name"></p>

    <p>money <input type="number" name="money"></p>

    <p><input type="submit"></p>
    <input type="button" value="ajax提交" id="d1">
</form>


<script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
            data:{'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},  //获取input提交给网页的name做对比
            success:function (res){

            }
        })
    })
</script>

2.自动获取scrf_token串

<form action="" method="post">
    {% csrf_token %}
    <p>username <input type="text" name="username"></p>

    <p>target_name <input type="text" name="target_name"></p>

    <p>money <input type="number" name="money"></p>

    <p><input type="submit"></p>
    <input type="button" value="ajax提交" id="d1">
</form>


<script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
            data:{'csrfmiddlewaretoken':'{{ csrf_token }}','username':'jack'},  // 将K:V键值对和浏览器中的cookie中对比,在csrf_token外面必须要添加引号,还可以在后面传值
            success:function (res){

            }
        })
    })
</script>

3.直接引入一个js模块

csrf相关装饰器

csrf是一个唯一标识,只有在进行第二次请求的时候才会去校验,get请求就不会校验,校验的位置在setting里面,就是post请求单注释的那个位置’django.middleware.csrf.CsrfViewMiddleware’

当我们又不一样的要求时:
整个Django项目都校验csrf但是某些视图函数类不想校验
整个Django项目都不校验csrf但是某些视图函数类需要校验

FBV添加装饰器方法

与正常函数添加装饰器一直

from django.views.decorators.csrf import csrf_exempt,csrf_portect
@csrf_exempt  # 全局csrf校验时,该装饰器作用是不校验此函数
@csrf_protect  # 注释掉csrf,该装饰器还是会校验此函数 
from django.views.decorators.csrf import csrf_exempt,csrf_protect
# @csrf_exempt  # 全局csrf校验时,该装饰器作用是不校验此函数
@csrf_protect # 注释掉csrf,该装饰器还是会校验此函数
def transfer_func(request):pass

CBV添加装饰器的多种方式
与正常情况不一致,需要引入method_decorator模块

# 引入模块
from django import views
from django.utils.decorators import method_decorator

# @method_decorator(csrf_protect, name='post')  # 方式2:单独生效
class MyView(views.View):
    @method_decorator(csrf_protect)  # 方式3:整个类中生效
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    # @method_decorator(csrf_protect)  # 方式1:单独生效
    def post(self, request):
        return HttpResponse('from cbv post view')

注意:有一个装饰器是特例,只能由一种添加方法>>>:csrf_exempt,只有在dispatch方法添加才会生效

from django.views.decorators.csrf import csrf_exempt
class MyView(views.View):
    @method_decorator(csrf_exempt)  # csrf_exempt只能通过第三种方式全类取消csrf校验
    def dispatch(request):
        return super().dispatch(request, *args, **kwargs)
    def get(request):pass
    def post(request):pass

原文地址:https://blog.csdn.net/shiyaopeng11/article/details/134587121

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_954.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注