Django中间件
1. 中间件是什么?
简单来讲,中间件类似于一个插件,在我们通过路由绑定函数进行视图方法实现之前,通过插入多个插件,在实现之前提前修改请求体或者提前返回结果
例如我们的业务需求:
需要实现访问网站的请求中,只要没有登录账号的就全部给他跳转到/login页面
按照以前的实现,我们需要在每个视图里面都加入一个session判断,没有的就返回重定向
但是有了中间件,我们就可以在请求达到视图函数之前,对所有的请求进行提前判断
2. 中间件的代码形式
2.1 函数格式编写
这里为什么要用闭包函数,是因为必须要实现一个类似于类的__ init __方法,所以才需要使用闭包
def simple_middleware(get_response):
# 要这样写,是因为中间件在程序启动的时候要进行初始化,所以初始化的时候,就会执行simple_middleware(get_response)
def middleware(request):
# 这里写需要实现的功能
response = get_response(request)
# 最后需要返回一个Response对象,如果希望不改变原本的返回就直接返回 get_response(request)
return response
return middleware
2.2 类格式编写
class SimpleMiddleware:
def __init__(self, get_response):
"""
这里用作初始化对象,设置了get_response属性
"""
self.get_response = get_response
def __call__(self, request):
# 这里写需要实现的功能,也就是执行视图函数或者[下一个中间件之前]要实现的功能
response = self.get_response(request)
# 返回Response对象,如果希望不改变原本的返回就直接返回 self.get_response(request)
return response
3. 中间件的注册
中间件需要在Django项目的setttings.py中进行注册
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",
'Django05.middleware.simple_middleware', # 注册我们的中间件,类了话传类名,方法传方法名
]
4. 系统默认中间件
-
django.middleware.security.SecurityMiddleware
负责处理安全相关的头部和操作,比如添加X-XSS-Protection头部和严格传输安全头部(STS)。
-
django.contrib.sessions.middleware.SessionMiddleware
处理会话相关的功能,包括初始化会话对象、处理会话数据的存储和访问,以及管理会话的生命周期。
-
django.middleware.common.CommonMiddleware
:提供一些通用的处理,比如设置响应头部、处理请求路径尾部的斜杠、处理URL重定向等。
-
django.middleware.csrf.CsrfViewMiddleware
:处理 CSRF(跨站请求伪造)保护。它会验证请求中的 CSRF token,并防止来自不受信任站点的 POST、PUT、DELETE 请求。
-
django.contrib.auth.middleware.AuthenticationMiddleware
:处理用户认证相关的功能。它会在每个请求中对用户进行认证,并将认证后的用户对象添加到
request.user
中。 -
django.contrib.messages.middleware.MessageMiddleware
:处理用户消息(如闪现消息)的功能。它在请求处理过程中,将消息存储在会话中,并在下一次请求时提取出来以便在模板中显示。
-
django.middleware.clickjacking.XFrameOptionsMiddleware
:处理点击劫持保护。它通过添加 X-Frame-Options 头部来阻止网页被嵌入到 frame 或 iframe 中,提高网站的安全性。
5. 中间件的执行顺序
简单来讲:
收到请求:顺序执行
返回请求:逆序执行
我们在settings.py中的中间件,会按照列表传入的顺序进行依次执行
下方的图,是中间件请求顺序的简单图解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bONbKg7g-1690628601824)(C:\Users\RYF55\AppData\Roaming\Typora\typora-user-images\image-20230729171053118.png)]
案例:
# 现在有两个中间件
# 1. 需要先进行用户是否登录的验证
# 2. 需要进行用户是否为管理员的验证
# 如果1验证不通过,就让用户去登录
# 如果2验证不通过,就返回状态码403
此时,我们请求的验证顺序是 1-2,所以注册中间件应该这样注册
MIDDLEWARE = [
验证登录中间件,
验证管理员中间件,
]
所以:
验证登录中间件 ->通过-> 验证管理员中间件 不通过 <-(最先返回不通过)
最终顺序就是:
收到请求,顺序执行|返回请求,逆序执行
6. 案例实践,定义一个中间件
需求分析:
- 如果用户请求的session中没有userid,那么视为用户没有登录
- 如果是GET请求没有登录,直接302重定向到 login 页面
- 如果是POST请求没有登录,则返回一个字符串,你没有登录
- 如果登录了,就正常执行请求
- 并且支持设置部分页面需要验证,例如login页面不需要验证登录,userinfo页面需要验证登录
6.1 定义中间件
6.1.1 函数方式定义中间件
"""
自定义Django请求中间件
"""
from django.shortcuts import redirect
from django.http import JsonResponse
def is_login_auth(get_response):
"""
定义验证用户是否登录中间件
:param get_response: 请求需要返回的Response对象(Django中间件通用定义方式)
"""
def middleware(request):
need_auth_path = [
'/userinfo/' # 需要进行验证登录有效性的路由
]
if request.path not in need_auth_path:
return get_response(request) # 如果路由不在验证列表中,则直接返回原请求对象
method = request.method # 获取请求方法
userid = request.session.get("userid") # 从session中读取userid
if userid: # 如果能读取到userid证明登录有效
return get_response(request) # 直接返回原请求对象
# 如果读取不到,则证明登录失效
if method == 'GET': # 如果是GET请求,就重定向到登陆页面
return redirect('login')
else: # 如果是POST请求,就返回JSON
return JsonResponse({"status": -1, "message": '登录失效!!!', "data": None})
return middleware
6.1.2 类定义中间件
from django.shortcuts import redirect
from django.http import JsonResponse
class LoginAuth:
"""
定义验证用户是否登录中间件
:param get_response: 请求需要返回的Response对象(Django中间件通用定义方式)
"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
"""
回调函数,返回Response对象
"""
need_auth_path = [
'/userinfo/' # 需要进行验证登录有效性的路由
]
if request.path not in need_auth_path:
return self.get_response(request) # 如果路由不在验证列表中,则直接返回原请求对象
method = request.method # 获取请求方法
userid = request.session.get("userid") # 从session中读取userid
if userid: # 如果能读取到userid证明登录有效
return self.get_response(request) # 直接返回原请求对象
# 如果读取不到,则证明登录失效
if method == 'GET': # 如果是GET请求,就重定向到登陆页面
return redirect('login')
else: # 如果是POST请求,就返回JSON
return JsonResponse({"status": -1, "message": '登录失效!!!', "data": None})
6.2 注册中间件
settings.py
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
# "django.middleware.csrf.CsrfViewMiddleware", # 取消csrf验证
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
'Django05.middleware.LoginAuth', # 使用类注册中间件
]
6.3 查看请求效果
下图是有session的情况,直接返回用户信息
没有session的情况,返回302重定向
ameOptionsMiddleware",
‘Django05.middleware.LoginAuth’, # 使用类注册中间件
]
## 6.3 查看请求效果
## **下图是有session的情况,直接返回用户信息**

## 没有session的情况,返回302重定向
