1 中间件的定义
-
中间件是 Django 请求/响应处理的钩子框架。它是一个轻量级的、低级的“插件”系统,用于全局改变 Django 的输入或输出。
-
每个中间件组件负责做一些特定的功能。例如,Django 包含一个中间件组件AuthenticationMiddleware,它使用会话将用户与请求关联起来。
-
他的文档解释了中间件是如何工作的,如何激活中间件,以及如何编写自己的中间件。Django 具有一些内置的中间件,你可以直接使用。它们被记录在 built-in middleware reference 中。
2 编写自己的中间件
- 中间件类必须继承django.utils.deprecation.MiddlewareMixin类
- 中间件类须实现下列五个方法中的一个或多个:
- process_request(self,reqyest) 执行路由之前被调用,返回None或者HttpResponse对象
- process_view(self,request,callback,callback_args,callback_kwargs)调用视图前被调用,在每个请求上调用,返回None或者HttpResponse对象
request 是一个 HttpRequest 对象。view_func 是一个 Django 将要使用的 Python 函数。(这是一个真实的函数对象,不是函数的名称);view_args 是一个用来传递给视图的位置参数列表,;view_kwargs 是一个用来传递给视图的关键字参数字典。view_args 和 view_kwargs 都不包含第一个视图参数 ( request )。 - get_response(self,request,response): 所有响应返回浏览器被调用,在每个请求上调用,返回HttpResponse对象
- process_exception(self,request,exception): request 是一个 HttpRequest 对象。 exception 是一个由视图函数引发的 Exception 对象。
当视图引发异常时,Django 会调用 process_exception()。process_exception() 应该返回 None 或 HttpResponse 对象。如果它返回一个 HttpResponse 对象,模板响应和响应中间件将被应用且会将结果响应返回浏览器。否则,就会开始默认异常处理( default exception handling )。
3 注册中间件
若要激活中间件组件,请将其添加到 Django 设置中的 MIDDLEWARE 列表中。
在 MIDDLEWARE 中,每个中间件组件由字符串表示:指向中间件工厂的类或函数名的完整 Python 路径。例如,这里创建的默认值是 django-admin startproject:
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',
]
Django 安装不需要任何中间件——如果您愿意的话,MIDDLEWARE 可以为空——但是强烈建议您至少使用CommonMiddleware
。
MIDDLEWARE 的顺序很重要,因为中间件会依赖其他中间件。例如:类 AuthenticationMiddleware 在会话中存储经过身份验证的用户;因此,它必须在 SessionMiddleware 后面运行 。中间件。Session中间件。请参阅 中间件顺序 ,用于一些关于 Django 中间件类排序的常见提示。
4. CSRF
你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全。
django中为了防范csrf跨域攻击,要求在html页面的form表单中增加{%csrf-token%},如果服务器收到的csrf-token值和后端不匹配,则认为是危险网站,返回403访问失败。
在django中需要在settings配置里面打开csrf中间件
特殊说明:
如果某个视图不需要进行csrf保护,可以用装饰器关闭对这个视图的检查。
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def my_view(request):
return HttpResponse("hello world")
5 练习
5.1 练习1
用中间件实现强制某个ip地址只能向/index 开头的地址发送5次请求。
提示:
request.META[‘REMOTE_ADDR’]可以获取远程客户端的IP地址
request.path_info可以得到客户端访问的请求路由信息
class VisitLimit(MiddlewareMixin):
visit_times = {}
def process_request(self, request):
# 实现强制某个ip地址只能向/test开头的地址发送5次请求。
ip_address = request.META['REMOTE_ADDR']
path_url = request.path_info
if not re.match('^/index', path_url):
return
else:
times = self.visit_times.get(ip_address, 0)
print('ip', ip_address, '已经访问', times)
self.visit_times[ip_address] = times+1
if times < 5:
return
else:
return HttpResponse("您已经访问过" + str(times) + '次,被禁止访问!')
5.2 练习2
用户登录验证中间件,访问除了登录页面url以外页面,进行登录验证。
class AuthMiddleware(MiddlewareMixin):
"""用户登录验证中间件"""
WHITE_LIST = [
"/views/user/verify",
"/views/user/login",
]
def process_request(self, request):
# 如果请求的url在白名单内,跳过检查
for path in self.WHITE_LIST:
if request.path.startswith(path):
return
# 进行登录检查
uid = request.session.get("uid")
if uid:
try:
request.user = User.objects.get(id=uid)
return
except User.DoesNotExist:
request.session.flush()
return render_json(None, code=error.LOGIN_ERROR)