django (中间件)
django中间件
首先django自带7个中间件,每个中间件都有各自的功能
并且django还支持程序员自定义中间件
你在用django开发项目的项目的时候,只要涉及到全局相关功能都可以使用中间件方便完成
django中间件是django的门户
1请求来的时候需要先经过中间件才能到达真正的django后端
2响应走的时候最后也需要经过中间件才能发送出去
django请求生命周期流程图
django中间件能够完成的事情
只要涉及到项目全局的功能,一定要想到中间件
1全局身份校验
2全局访问频率校验
3全局权限校验
django中间件
django支持程序员自定义中间件并且暴露给程序员的5个自定义的方法
1必须掌握
process_request
process_response
2了解即可
process_view
路由匹配成功之后执行视图函数之前,会自动执行中间件里面的
process_template_response
返回HTTPResponse对象有render属性的时候才会触发
顺序是按照配置文件中注册的中间从下往上依次通过
process_exception
当视图函数出现异常情况下触发
顺序是按照配置文件中注册的中间件从上往下的顺序依次经过
如何自定义中间件
1在项目名或者应用名下创建一个任意名称的文件夹
2在该文件夹创建一个任意名称的py文件
3在该py文件内需要书写类(这个类必须要继承MiddlewareMixin)
然后在这个类里面就可以自定义5个方法
(这5个方法并不是全部都需要书写,用几个写几个)
4需要将类的路径以字符串的形式注册到配置文件中才能生效
process_request方法就是用来做全局相关的所有限制功能
1请求来的时候需要经过每一个中间件里面的process_request方法
结果的顺序是按照配置文件中注册的中间件从上往下的顺序依次执行
2如果中间件里面没有定义该方法,那么直接跳过执行下一个中间件
3如果该方法返回HttpResponse对象,那么请求将不再继续往后执行
而是直接原路返回(校验失败不允许访问...)
process_response
1响应走的时候需要经过每一个中间件里面的process_response方法
该方法有两个额外参数request,response
2该方法必须返回一个HttpResponse对象
2.1默认返回的就是形参response
2.2你也可以自己返回自己的
3顺序是按照配置文件中注册了中间价从下往上依次执行经过
如果你没有定义的话,直接跳过执行下一个
如果第一个process_request方法已经返回了一个HttpResponse对象,那么响应
走的时候是经过所有的中间里面的process_response,就会直接走同级别的
process_response返回
flask框架也有一个中间件但是它的规律
只要返回数据了就必须经过所有中间件里面的类似于process_response方法
目前可以说是所有web框架里面写的最好的
csrf跨站请求伪造
内部本质
我们在钓鱼网站的页面,针对对方账户,只给用户提供一个没有name属性的
普通input框,然后我们在内部隐藏一个已经写好的name和value的input框
csrf跨站请求伪造
网站在给用户返回一个具有提交数据功能页面的时候会给这个页面加一个唯一标识
当这个页面朝后端发送post请求的时候,我们后端会先校验唯一标识,如果唯一标识
不对直接拒绝(403 forbbiden)如果成功则正常执行
如何符合校验
form表单
{ % csrf_token % }
ajax
第一种 利用标签查找获取页面上的随机字符串
第二种 利用模语法提供的快捷书写
第三种 通用方式直接拷贝js代码并应用到自己的html页面
csrf相关装饰器
1网站整体都不校验csrf,就简单几个视图函数要校验
2网站整体都校验csrf,就简单几个视图函数不校验
csrf_protect 需要校验
针对csrf_protect符合我们之前所学的装饰器的三种玩法
csrf_exempt 不要校验
针对csrf_exempt只能给dispatch方法加才有效
补充知识点
能够以字符串的形式帮你导入模块,该方法最小只能到py文件名
模块 importlib
import importlib
res = 'myfile.b'
ret = importlib.import_module( res )
基于django中间件一个重要的编程思想
import settings
import importlib
def send_all( content ):
for path_str in settings.NOTIFY_LIST:
module_path,class_name = path_str.rsplite( ' , ' , maxsplit=1)
1利用字符串导入模块
module = importlib.import_module(mudule_path)
2利用反射获取类名
cls = getattr(module,class_name)
3生成类的对象
obj = cls( )
4利用鸭子类模型调用sent方法
obj.sent( content )