设为首页 收藏本站
查看: 807|回复: 0

Python深入了解中间件及插拔式思想

[复制链接]
累计签到:528 天
连续签到:1 天
发表于 2022-11-5 01:25:12 | 显示全部楼层 |阅读模式
# django中间件前戏
django中间件是django的门户
    1、请求来的时候需经过中间件才能到达真正的django后端
    2、相应走的时候也需要中间件发送出去
django自带7个中间件
[django请求生命周期流程图]
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',
]
class SessionMiddleware(MiddlewareMixin):
    def process_request(self, request):
        session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
        request.session = self.SessionStore(session_key)
    def process_response(self, request, response):
        return response

class CsrfViewMiddleware(MiddlewareMixin):
    def process_request(self, request):
        csrf_token = self._get_token(request)
        if csrf_token is not None:
            # Use same token next time.
            request.META['CSRF_COOKIE'] = csrf_token
    def process_view(self, request, callback, callback_args, callback_kwargs):
        return self._accept(request)
    def process_response(self, request, response):
        return response

class AuthenticationMiddleware(MiddlewareMixin):
    def process_request(self, request):
        request.user = SimpleLazyObject(lambda: get_user(request))
# 我们会发现这些中间件都有一些共同方法[django支持程序员自定义中间件并且暴露了5个可以自定义的方法]
1、必须掌握
    process_request
    process_response

2、了解即可
    process_view
    process_template_response
    process_exception

def process_request(self, request):def process_response(self, request, response):def process_view(self, request, callback, callback_args, callback_kwargs):def process_template_response(self,request,response):def process_exception(self,request,exception):
# 接下来我们可以根据这些公共方法自己可以自定义中间件# 如何自定义中间件
1、在项目名或者应用名下创建一个任意名称的文件夹
2、在该文件夹内创建一个任意名称的py文件
3、在该py文件需要书写类(必须继承MiddlewareMixin)
    然后在这个类里面就可以自定义五个方法了
    (这个5个方法不是全部都书写的,用几个写几个)
4、需要将类的路径以字符串的形式注册到配置文件中才能生效
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',
    '自己写的中间件2',


from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,HttpResponse


class MyMiddleware1(MiddlewareMixin):
    def process_request(self,request):# 只要处理请求的都需要带一个request的形参
        print('我是第一个自定义中间件的process_request方法')

    def process_response(self,request,response):
        print('我是第一个自定义中间件的process_response方法')
        return response

    def process_view(self,request,view_name,*args,**kwargs):
        print(view_name,args,kwargs)
        print('我是第一个自定义中间件里面的process_view')

    def process_template_response(self,request,response):
        print('我是第一个自定义中间件里的process_template_response')
        return response

    def process_exception(self,request,exception):
        print('我是中间件里面的process_exception')
        print(exception)
class MyMiddleware2(MiddlewareMixin):
    def process_request(self,request):# 只要处理请求的都需要带一个request的形参
        print('我是第二个自定义中间件的process_request方法')

    def process_response(self,request,response):
        print('我是第二个自定义中间件的process_response方法')
        return response

    def process_view(self,request,view_name,*args,**kwargs):
        print(view_name,args,kwargs)
        print('我是第er 个自定义中间件里面的process_view')

    def process_template_response(self,request,response):
        print('我是第一个自定义中间件里的process_template_response')
        return response

    def process_exception(self,request,exception):
        print('我是中间件里面的process_exception')
        print(exception)
# 开始刨析必会的request和response的方法1、必须掌握
    [可以用来进行全局的全局的校验,是否为黑名单,数据是否合法-还可以书写一些防爬措施
    [process_request]:针对请求来的时候执行,上从而下
        1、请求来的时候需要经过每一个经过中间件的process_request方法
        经过的顺寻是按照配置文件中注册中间件从上往下顺序一次执行
        2、如果中间件里面没有定义该方法,那么直接跳过执行下一个
        3、如果该方法返回了HttpResponse对象,那么请求将不再继续往后执行
        而是直接原路返回(校验失败不允许访问...)
        [process_request方法就是用来做全局相关的所有限制功能]
-
    [process_response]-
    [只要用来返回后端传来的HttpResponse对象]
          1、响应走的时候需要经过每一个中间件里面的process_response方法
          该方法有两个参数,request,response
          2、该方法必须返回HttpResponse对象
              1、默认返回的就是形参response(可以实现狸猫换太子自己传回的其他HttpResponse结果)
              2、你也可以自己返回自己的,后买你拿到的所有的都是你设定的了,就不是后端的了
          3、顺序按照配置文件的注册的中间件从下到上,如果没有定义,跳过到下一个

[研究如果在第一个process_request方法就已经返回HttpResponse对象]
那么在响应走的时候是经过所有的中间件 process_response还是有其他情况?
    就是会直接走[同级别的process_response返回,下面直接拦截了

[flask框架也有一个中间件但是他的规律]
    只要返回数据了就必须经过所有的中间件类似于process_response方法
# 了解的是知识点
[process_view]-
    [路由匹配成功之后,视图函数之前,会自动执行中间件里面的该方法]
    经过的顺序还是按照配置文件中注册中间件从上往下顺序一次执行
[process_template_response]-比较难触发,一般不用
    [返回的有HttpResponse对象有render属性时候时候触发]
    顺序是按照配置文件的注册的中间件从下到上
[process_exception]
    当视图函数出现了异常的情况下触发
    顺序是按照配置文件中注册了的中间件顺序从下到上
# 钓鱼网站与csrf的由来# csrf 跨站请求伪造
钓鱼网站
    我搭建一个跟正规网站一模一样的界面(中国银行)
    用户不小心进入到了我们的网站,用户给某人打钱
    打钱的操作确确实实提交给中国银行的系统,用户的钱少了
    但是唯一不同的是打钱的账户不是客户想转的账户

大学英语四六级
    考之前需要登录缴费

内部本质
    内部的input的框没有name和value属性,自己手动加了一个input框然后在input框添加
    name='target'和value='jason'属性在用hidden隐藏起来,然后提交post请求得到name和value所对应的值进行操作

如何规避上述的问题
    csrf跨站请求伪造验证
        当网站给用户端返回一个具有提交数据功能页面的时候会给这个页面加一个唯一标识
        当这个页面朝后端发送post请求的时候 我的后端会先校验唯一标识,如果唯一标识不对直接拒绝
        (403 forbidden)如果成功则正常执行
# csrf如何安全实现form表单和Aajx请求的校验请求# 如何符合验证
[form表单post方法如何引用=
[{% csrf_token %}]
<form action=""method="post">
    {% csrf_token %}
    <p>用户名:<input type="text" name="username"></p>
    <p>target_user:<input type="text" name="target_user"></p>
    <p>money:<input type="text" name="money"></p>
    <input type="submit">
</form>

[ajax发送post请求如何引用]
?[第三种通用方法步骤]
1、现在静态文件配置STATICFILES_DIRS =[os.path.join(BASE_DIR,'static')]
2、{% load static %}
<script src="{% static 'js/mysetup.js' %}"></script>

<button id="d1">ajax请求</button>
{% load static %}
<script src="{% static 'js/mysetup.js' %}"></script>
<script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
            // [第一种 利用标签查找获取也买你上的随机字符串]
            {#data:{"username":"jason","csrfmiddlewaretoken":$('[name=csrfmiddlewaretoken]').val()}#}
            // [第二种 利用模板语法提供的快捷书写]
            {#data:{"username":"jason","csrfmiddlewaretoken":'{{ csrf_token }}'},#}
            // 第三种 通用方式 直接拷贝js代码并应用到自己的html页面上即可
            data:{"username":"jason"},
            success:function (){

            }
        })
    })
</script>

[本地代码static/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);
            // 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);
    }
  }
});
# 如何实现只给部分CBV和FBV添加中间键的csrf需求# csrf相关修饰器
[1、网站整体不校验csrf,就单单几个视图函数需要校验]

[2、网站整体都不校验,就单单九个视图函数校验]

"""
-
[csrf_protect 需要校验
    针对csrf_protect符合我们所学的CBV三种玩法]
-[csrf_exempt 豁免/不校验
不需要校验
    针对csrf_exempt只能给dispatch方法加才有效]
"""

# @csrf_exempt
# @csrf_protect
# FBV使用和CBV都可以

def transfer(request):
    if request.method =='POST':
        username = request.POST.get('username')
        target_user = request.POST.get('target_user')
        money = request.POST.get('money')
        print('%s
%s转了%s'%(username,target_user,money))
    return render(request,'transfer.html')
from django.utils.decorators import method_decorator
from django.views import View

# CBV使用(csrf_protect都可以通用)(但是csrf_exempt只有dispatch可以)
from django.views import View
@method_decorator(csrf_protect,name='post')  #
[针对第二种方法可以]
class MyCsrfToken(View):
    def dispatch(self, request, *args, **kwargs): #
[第三种也可以]
        return super(MyCsrfToken,self).dispatch(request,*args,**kwargs)
    def get(self,request):
        return HttpResponse('get')
    # @method_decorator(csrf_protect) #
[针对第一种方法可以]
    def post(self,request):
        return HttpResponse('post')

# 补充拓展知识点,插拔式思想
[重要代码]
import importlib
res = 'myfile.b'
ret = [importlib.import_module(res)]
print(ret)# <module'b'...>模块对象 等价于
[importlib.import_module(res)] == [from myfile import b]
# 后续补充完善的插拔式请求,之前也更新过,但是感觉思路不清晰,明天我再整理更新一下
def send_all(content):
    for path_str in settings.NOTIFY_LIST:
        module_path,class_name=path_str.rsplit('.',maxsplit=1)
        # module_path = 'notify.email'  class_name='Email'
        # 1、利用字符串导入模块
        module= importlib.import_module(module_path) # from notify import email
        # 2、利用反射得到属性名
        cls=getattr(module,class_name) # 通过email得到Email的属性,所以得到了类名
        # 3、生成对象
        obj=cls()
        # 4、利用鸭子类型调用send方法
        obj.send(content)


中间件_20221105.jpg

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-1002627-1-1.html 上篇帖子: Djangp中的CBV如何添加装饰器 下篇帖子: Django之auth模块
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表