Django之中间件与CSRF_TOKEN

文章目录

流程图介绍中间件

一、什么是中间件

Django中间件类似于django的门户,所有的请求来和响应走走必须经过中间件

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

Django官方中间件的定义:

python 复制代码
	Middleware is a framework of hooks into Django's request/response processing. 
	It's a light, low-level "plugin" system for globally altering Django's input or output.

中间件它的执行位置在web服务网关接口之后,在路由匹配之前执行的

二、中间件有什么用

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

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

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

python 复制代码
	'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',
	]

1.django.middleware.security.SecurityMiddleware

做了一些安全处理的中间件。比如设置XSS防御的请求头,比如做了http协议转为https协议的工作等。

2.django.contrib.sessions.middleware.SessionMiddleware

session中间件。会给request添加一个处理好的session对象。

3.django.middleware.common.CommonMiddleware

通用中间件,会处理一些URL,比如baidu.com会自动的处理成www.baidu.com

4.django.middleware.csrf.CsrfViewMiddleware

保护中间件,在提交表单的时候必须加入csrf_token,cookie中也会生成一个名叫csrftoken的值,也会在header中加入一个HTTP_X_CSRFTOKEN的值来放置CSRF攻击。SessionMiddleware必须出现在CsrfMiddleware之前。

5.django.contrib.auth.middleware.AuthenticationMiddleware

用户授权中间件。会给reqeust添加一个user对象的中间件。该中间件必须在sessionmiddleware后面。

6.django.contrib.messages.middleware.MessageMiddleware

消息处理中间件。为了在多个模版中可以使用我们返回给模版的变量,并且简化操作。

7.django.middleware.clickjacking.XFrameOptionsMiddleware

防止通过浏览器页面跨Frame出现clickjacking(欺骗点击)攻击出现。

中间件的执行顺序

每一个中间件在请求来的时候或者响应的时候都具有一定的作用。


三、Django自定义中间件

Django给我们提供了创建自定义中间件的方式,通过创建自定义中间件来实现全局的功能,例如全局用户黑名单校验、全局用户访问频率校验、网站全局用户身份校验等等。

中间件中主要方法及作用

python 复制代码
	'中间件类必须继承自django.utils.deprecation.MiddlewareMixin类'
	
	process_request(self,request)
	用途:过滤请求
	'''
	1.请求来的时候会按照配置文件中注册了的中间件,从上往下依次执行每一个中间件里面的porcess_request方法,如果没有则直接跳过
	2.该方法如果返回了HttpResponse对象,那么请求不会再往后执行,原路返回
	'''
	
	process_view(self, request, callback, callback_args, callback_kwargs)
	用途:用于代码层面的替换和过滤,这个方法可以拿到视图函数的参数
	'''当路由匹配成功之后,执行视图函数之前,自动触发'''
	
	process_template_response(self,request,response)
	'''当视图函数返回的数据对象中含有render属性对应render函数才会触发'''
	
	process_exception(self, request, exception)
	用途:用于一般用于捕获发生的异常,并将其邮件发送给开发人员
	'''当视图函数报错之后,自动触发'''
	
	process_response(self, request, response)
	'''
	1.响应走的时候会按照配置文件中注册了的中间件,从下往上依次执行每一个中间件里面的process_response方法,如果没有则直接跳过
	2.该方法有两个形参request和response,并且默认情况下应该返回response
	3.该方法也可以自己返回HttpResponse对象,相当于狸猫换太子
	'''
'如果请求的过程中process_request方法直接返回了HttpResponse对象那么会原地执行同级别process_response返回后直接返回(flask则不同)'

创建自定义中间件的步骤:

python 复制代码
	1.在项目名下或者任意的应用名下创建一个文件夹
	2.在该文件夹内创建一个任意名称的py文件
	3.在该py文件中编写一个自定义的中间件类,并且必须继承MiddlewareMixin
	4.紧接着去settings配置文件中注册中间件

process_request与process_response方法

当用户发起请求的时候会依次执行经过的所有中间件,这个时候的请求首先进入process_request,最后到达views的函数中,views函数处理后,在依次穿过中间件,这个时候是process_response,最后返回给请求者。

我们要自己定义中间件的话,需要写一个类,并且继承MiddlewareMixin

python 复制代码
	from django.utils.deprecation import MiddlewareMixin

第一步:需要建立一个py文件夹来编写我们自定义的中间件,建议在应用层下面创建。

app-------》Middleware-----》middle.py

python 复制代码
	from django.utils.deprecation import MiddlewareMixin

	class MyMiddleware1(MiddlewareMixin):
	    def process_request(self,request):
	        print('这是第一个中间件的process_request')
	
	    def process_response(self,request,response):  # 响应
	        print('这是第一个中间件的process_response')
	        return response
	
	
	class MyMiddleware2(MiddlewareMixin):
	    def process_request(self,request):
	        print('这是第二个中间件的process_request')
	
	    def process_response(self,request,response):  # 响应
	        print('这是第二个中间件的process_response')
	        return response

第二步:在settings.py文件里面加入我们自定义的中间件

python 复制代码
	MIDDLEWARE = [
		# settings这个列表中存储的其实就是一个个中间件的路径
	    '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',
	    #下面两个就是自定义的中间件路径地址
	    'app.Middleware.middle.MyMiddleware1',
	    'app.Middleware.middle.MyMiddleware2',
	]

第三步:定义视图函数

python 复制代码
	'记得别忘记配置路由'
	def func(request):
	    print('from func')
	    return HttpResponse('from func')

当我们浏览器朝服务端发送请求,必定会经过我们刚才定义的中间件

process_request方法的request则是请求,response则是视图函数返回的内容到了中间件里面,然后由中间件return出去。所以我们是可以在process_response里面不写return视图函数返回的内容,自己定义内容返回。


从下图看,正常的情况下按照绿色的路线进行执行,假设中间件1有返回值,则按照红色的路线走,直接执行该类下的process_response方法返回,后面的其他中间件就不会执行。

也就是说中间件的process_request方法使用了return,那么其后面的中间件将不再执行,直接执行该中间件和其上面中间件的process_response方法,最终将某个process_request里面的return值返回给请求者。

由此总结:

  • 中间件的process_request方法是在执行视图函数之前执行的。
  • 当配置多个中间件时,会按照MIDDLEWARE中的注册顺序,也就是列表的索引值,从前到后依次执行的。
  • 不同中间件之间传递的request都是同一个对象

多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的,也就是说第一个中间件的process_request方法首先执行,而它的process_response方法最后执行,最后一个中间件的process_request方法最后一个执行,它的process_response方法是最先执行的。


process_view方法

该方法格式:process_view(request, view_func, view_args, view_kwargs)

process_view方法的四个参数:

  • request:HTTPRequest对象
  • view_func:Django即将调用的视图函数
  • view_args:将传递给视图的位置参数的元组
  • view_kwargs:是将传递给视图的关键字参数的字典

view_args和view_kwargs都不包含第一个视图函数(request)

process_view方法是在视图函数之前,process_request方法之后执行的。

它应该返回None或一个HttpResponse对象,如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。如果它返回一个HttpResponse对象,Django不会调用适当的视图函数。它将执行中间件的process_response方法并将应用到该HttpResponse并返回结果。

自定义中间件:

python 复制代码
	记得需要注册自定义中间件
	from django.utils.deprecation import MiddlewareMixin
	class Md1(MiddlewareMixin):
	    def process_request(self,request):
	        print('M1请求来时,校验')
	
	    def process_response(self,reqeust,response):
	        print('M1返回数据时,对数据进行处理')
	        return response
	
	    def process_view(self,request,view_func,view_args,view_kwargs):
	        print('我在只给你view函数前执行!')

	class Md2(MiddlewareMixin):
	    def process_reqeust(self,request):
	        print('M2请求来时,校验')
	
	    def process_response(self,request,response):
	        print('M2返回数据时,对数据进行处理')
	        return response
	
	    def process_view(self,request,view_func,view_args,view_kwargs):
	        pass

	执行结果》》》》:
		M1请求来时,校验
		我在只给你view函数前执行!
		from func
		M2返回数据时,对数据进行处理
		M1返回数据时,对数据进行处理

下图分析上面代码的执行过程:

当最后一个中间件的process_reqeust到达路由关系映射之后,返回到中间件1的process_view,然后依次往下,到达views函数,最后通过process_response依次返回到达用户。

注意:process_view如果有返回值,会越过其他的process_view以及视图函数,但是所有的process_response都还会执行。


process_exception

process_exception(self, request, exception)

该方法两个参数:

  • 一个HttpRequest对象
  • 一个exception是视图函数异常产生的Exception对象。

这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个None也可以是一个HttpResponse对象。如果是HttpResponse对象,Django将调用模板和中间件中的process_response方法,并返回给浏览器,否则将默认处理异常。如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行。

视图函数制造错误

python 复制代码
	def index(request):
    print('index视图函数执行了')
    lis = [1,2,3]
    lis[4]

自定义中间件:

python 复制代码
	class Md1(MiddlewareMixin):
	    def process_request(self,request):
	        print("Md1请求")
	        
	    def process_response(self,request,response):
	        print("Md1返回")
	        return response
	
	    def process_view(self, request, callback, callback_args, callback_kwargs):
	
	        print("md1 process_view...")
	
	    def process_exception(self,request,exception):
	        print("md1 process_exception...")


	class Md2(MiddlewareMixin):
	    def process_request(self,request):
	        print("Md2请求")
	
	    def process_response(self,request,response):
	        print("Md2返回")
	        print(response.content)
	        return response
	
	    def process_view(self, request, view_func, view_args, view_kwargs):
	        print("md2 process_view...")
	
	    def process_exception(self, request, exception):
	        print("md2 process_exception...")
	        return HttpResponse(exception)


		执行结果》》》》:
			Md1请求
			Md2请求
			md1 process_view...
			md2 process_view...
			index视图函数执行了
			md2 process_exception...
			Md2返回
			b'list index out of range'
			Md1返回

当process_exception进行return HttpResponse后,process_response方法就会拿到其返回的数据。

当views出现错误时流程图如下:

process_template_response(不常用)

该方法对视图函数返回值有要求,必须是一个含有render方法类的对象,才会执行此方法。

process_template_response 函数是在视图函数执行完后立即执行的

视图

python 复制代码
	def index(request):
	    print("这里是 index 页面")
	    repsponse = HttpResponse("这里是主页面 index")
	
	    def render():
	        print("这里是 index 函数里的 render 方法")
	        return HttpResponse("index")
	
	    repsponse.render = render
	    return repsponse

自定义中间件

python 复制代码
	class Md2(MiddlewareMixin):
	    def process_request(self,request):
	        print("Md2请求")
	
	    def process_response(self,request,response):
	        print("Md2返回")
	        return response
	
	    def process_view(self, request, view_func, view_args, view_kwargs):
	        print(view_func)
	        print("md2 process_view...")
	
	    def process_template_response(self, request, response):
	        print("视图函数执行完毕,且返回了render")
	        return response
		
		
		执行结果》》》》:
			Md2请求
			md2 process_view...
			这里是 index 页面
			视图函数执行完毕,且返回了render
			这里是 index 函数里的 render 方法
			Md2返回

四、CSRF_TOKEN

相关推荐
Java水解10 分钟前
Django实现接口token检测的实现方案
后端·django
飞Link13 分钟前
【Django】Django 调用外部 Python 程序的完整指南
后端·python·django·sqlite
码界奇点3 小时前
基于Django与Vue.js的RBAC权限管理系统设计与实现
vue.js·python·车载系统·django·毕业设计·源代码管理
计算机学姐7 小时前
基于Python的智能点餐系统【2026最新】
开发语言·vue.js·后端·python·mysql·django·flask
计算机学姐1 天前
基于Python的在线考试系统【2026最新】
开发语言·vue.js·后端·python·mysql·django·flask
码界奇点1 天前
基于Django REST framework与Vue的前后端分离后台管理系统设计与实现
vue.js·后端·python·django·毕业设计·源代码管理
Q_Q5110082851 天前
python+springboot+django/flask基于深度学习的音乐推荐系统
spring boot·python·django·flask·node.js·php
Q_Q5110082851 天前
python+springboot+django/flask基于深度学习的淘宝用户购物可视化与行为预测系统
spring boot·python·django·flask·node.js·php
sugar椰子皮1 天前
【爬虫框架-6】中间件的另一种写法实现
爬虫·中间件
Q_Q5110082851 天前
python+django/flask+vue基于spark的西南天气数据的分析与应用系统
spring boot·python·spark·django·flask·node.js