个人网站 备案 广告,东莞建设网站公司简介,网站开发结论,php网站建设实例Django - 中间件 一. 什么是中间件 官方: 中间件是一个用来处理Django的请求和相应的框架级别的钩子, 他是一个轻量, 低级别的插件系统, 用于在全局范围内改变Django的输入和输出, 每个中间件都负责做一些特定的功能. 大白话: 中间件是帮助我们在视图函数执行之前和执行之后都可… Django - 中间件 一. 什么是中间件 官方: 中间件是一个用来处理Django的请求和相应的框架级别的钩子, 他是一个轻量, 低级别的插件系统, 用于在全局范围内改变Django的输入和输出, 每个中间件都负责做一些特定的功能. 大白话: 中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作, 本质就是一个自定类, 类中定义了几个方法, 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,
] 二. 定义中间件 中间件定义可以定义五个方法, (主要的是 process_request和 process_response) process_request(self.rerquest) process_view(self, request, view_func, view_args, view_kwargs) process_template_response(self, request, response) process_exception(self, request, exception) process_response(self, request, respoonse) 以上方法的返回值可以是None或HttpResponse对象, 如果是None, 则继续按照django定义的规则向后继续进行, 如果是HttpResponse对象, 则直接将该对象返回给用户. 1. process_request(self.rerquest) 执行时间: 在视图函数执行之前 参数: rsquest -- 跟视图函数中的是同一个 执行顺序: 按照注册顺序, 顺序执行 返回值: None -- 正常路程 HttpResponse对象 -- 不执行后面中间中的procrss_request方法, 不执行视图函数, 直接执行当前中间件中的process_response 方法, 后面正常走. from django.utils.deprecation import MiddlewareMixinclass MD1(MiddlewareMixin):def process_request(self, request):print(MD1里面的 process_request)class MD2(MiddlewareMixin):def process_request(self, request):print(MD2里面的 process_request) 在settings.py的MIDDLEWARE配置项上述两个自定义中间件: 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,middlewares.MD1, # 自定义中间件MD1middlewares.MD2 # 自定义中间件MD2 总结: 中间件的process_request方法是在执行视图函数之前执行的。当配置多个中间件时会按照MIDDLEWARE中的注册顺序也就是列表的索引值从前到后依次执行的。不同中间件之间传递的request都是同一个对象 2. process_response(self, request, respoonse) 执行时间: 在视图函数执行之后, process_request之后, 路由匹配之后 参数: request -- 跟函数中的是同一个 response -- 视图函数中传递的相应对象 执行顺序: 按照注册顺序, 倒叙执行 返回值: None --正常流程 HttpResponse对象: 必须是相应对象 from django.utils.deprecation import MiddlewareMixinclass MD1(MiddlewareMixin):def process_request(self, request):print(MD1里面的 process_request)def process_response(self, request, response):print(MD1里面的 process_response)return responseclass MD2(MiddlewareMixin):def process_request(self, request):print(MD2里面的 process_request)def process_response(self, request, response):print(MD2里面的 process_response)return response 总结: process_response方法是在视图函数之后执行的并且顺序是MD1比MD2先执行。(此时settings.py中 MD2比MD1先注册) 多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的也就是说第一个中间件的process_request方法首先执行而它的process_response方法最后执行最后一个中间件的process_request方法最后一个执行它的process_response方法是最先执行。 3.process_view(self, request, view_func, view_args, view_kwargs) 执行时间: 在process_request方法之后, 在视图函数执行之前 参数: request -- 跟视图函数的是同一个 view_func -- 视图函数 view_args -- 视图函数的位置函数 view_kwargs -- 视图函数的关键字参数 执行顺序: 按照注册顺序 顺序执行 返回值: None -- 正常执行 HttpResponse对象 -- 不执行后面中间中的process_view方法不执行视图函数直接执行最后一个中间件中的process_response方法后面正常走 from django.utils.deprecation import MiddlewareMixinclass MD1(MiddlewareMixin):def process_request(self, request):print(MD1里面的 process_request)def process_response(self, request, response):print(MD1里面的 process_response)return responsedef process_view(self, request, view_func, view_args, view_kwargs):print(- * 80)print(MD1 中的process_view)print(view_func, view_func.__name__)class MD2(MiddlewareMixin):def process_request(self, request):print(MD2里面的 process_request)def process_response(self, request, response):print(MD2里面的 process_response)return responsedef process_view(self, request, view_func, view_args, view_kwargs):print(- * 80)print(MD2 中的process_view)print(view_func, view_func.__name__) 4. process_exception(self, request, exception) 执行时间出现异常的时候才执行 参数request ——》 跟视图函数中的是同一个 exception——》 异常对象 执行顺序按照注册顺序 倒叙执行 返回值None 正常流程 HttpResponse对象不执行后面中间中的process_exception方法直接执行最后一个中间件中的process_response方法后面正常走 from django.utils.deprecation import MiddlewareMixinclass MD1(MiddlewareMixin):def process_request(self, request):print(MD1里面的 process_request)def process_response(self, request, response):print(MD1里面的 process_response)return responsedef process_view(self, request, view_func, view_args, view_kwargs):print(- * 80)print(MD1 中的process_view)print(view_func, view_func.__name__)def process_exception(self, request, exception):print(exception)print(MD1 中的process_exception)class MD2(MiddlewareMixin):def process_request(self, request):print(MD2里面的 process_request)def process_response(self, request, response):print(MD2里面的 process_response)return responsedef process_view(self, request, view_func, view_args, view_kwargs):print(- * 80)print(MD2 中的process_view)print(view_func, view_func.__name__)def process_exception(self, request, exception):print(exception)print(MD2 中的process_exception) 5. process_template_response(self, request, response) 执行时间视图函数返回的response对象有一个叫render的方法 参数request ——》 跟视图函数中的是同一个 response ——》 视图函数中传递的响应对象 执行顺序按照注册顺序 倒叙执行 返回值必须返回response对象 class MD1(MiddlewareMixin):def process_request(self, request):print(MD1里面的 process_request)def process_response(self, request, response):print(MD1里面的 process_response)return responsedef process_view(self, request, view_func, view_args, view_kwargs):print(- * 80)print(MD1 中的process_view)print(view_func, view_func.__name__)def process_exception(self, request, exception):print(exception)print(MD1 中的process_exception)return HttpResponse(str(exception))def process_template_response(self, request, response):print(MD1 中的process_template_response)return responseclass MD2(MiddlewareMixin):def process_request(self, request):print(MD2里面的 process_request)def process_response(self, request, response):print(MD2里面的 process_response)return responsedef process_view(self, request, view_func, view_args, view_kwargs):print(- * 80)print(MD2 中的process_view)print(view_func, view_func.__name__)def process_exception(self, request, exception):print(exception)print(MD2 中的process_exception)def process_template_response(self, request, response):print(MD2 中的process_template_response)return response 三. 中间件的执行流程 四. 中间件版登录注册 注意: 要把session 同步到数据库中 urls.py from django.conf.urls import url
from django.contrib import admin
from app01 import viewsurlpatterns [url(r^admin/, admin.site.urls),url(r^login/$, views.login, namelogin),url(r^index/$, views.index, nameindex),url(r^home/$, views.home, namehome),
] urls.py views.py from django.shortcuts import render, HttpResponse, redirectdef index(request):return HttpResponse(this is index)def home(request):return HttpResponse(this is home)def login(request):if request.method POST:user request.POST.get(user)pwd request.POST.get(pwd)if user alex and pwd alex3714:# 设置sessionrequest.session[user] user# 获取跳到登陆页面之前的URLnext_url request.GET.get(next)# 如果有就跳转回登陆之前的URLif next_url:return redirect(next_url)# 否则默认跳转到index页面else:return redirect(/index/)return render(request, login.html) views.py login.html !DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivx-ua-compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1title登录页面/title
/head
body
form action{% url login %} methodpost{% csrf_token %}plabel foruser用户名/labelinput typetext nameuser iduser/pplabel forpwd密 码/labelinput typetext namepwd idpwd/pinput typesubmit value登录
/form
/body
/html login.html middlewares.py rom django.utils.deprecation import MiddlewareMixinclass AuthMD(MiddlewareMixin):white_list [/login/, ] # 白名单black_list [/black/, ] # 黑名单def process_request(self, request):from django.shortcuts import redirect, HttpResponsenext_url request.path_infoprint(request.path_info, request.get_full_path())# 黑名单的网址限制访问if next_url in self.black_list:return HttpResponse(This is an illegal URL)# 白名单的网址或者登陆用户不做限制elif next_url in self.white_list or request.session.get(user):returnelse:return redirect(/login/?next{}.format(next_url)) middlewares.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,middlewares.AuthMD
] settings.py AuthMD中间件注册后所有的请求都要走AuthMD的process_request方法。 如果URL在黑名单中则返回This is an illegal URL的字符串 访问的URL在白名单内或者session中有user用户名则不做阻拦走正常流程 正常的URL但是需要登录后访问让浏览器跳转到登录页面。 注AuthMD中间件中需要session所以AuthMD注册的位置要在session中间的下方。 # visit_dict {}
# class Throttle(MiddlewareMixin):
#
# def process_request(self, request):
# # 获取到ip
# ip request.META.get(REMOTE_ADDR)
# # 获取到访问记录
# history visit_dict.get(ip, [])
# if not history:
# visit_dict[ip] history
#
# now time.time()
# new []
# for i in history:
# if now - i 5:
# new.append(i)
# for i in new:
# history.remove(i)
#
# while history and now - history[-1] 5:
# history.pop()
#
# if len(history) 3:
# return HttpResponse(访问频率太快了)
#
# history.insert(0, now) 中间件应用, 限制时间内登录次数 一 class Throttle(MiddlewareMixin):def process_request(self, request):history request.session.get(history, [])now time.time()while history and now - history[-1] 10:history.pop()if len(history) 3:return HttpResponse(你的访问频率太快)history.insert(0, now)request.session[history] history 中间件应用, 限制时间内登录次数 二 五. 补充 1. 跨站请求伪造, csrf中间件 两个装饰器 from django.views.decorator.csrf import csrf_exempt, csrf_protect carf_exempt -- 给视图加上装饰器后, 当前的视图不需要CSRF校验 csrf_protect -- 给视图加上装饰器后, 当前的视图需要CSRF校验 2. process_request 从cookie中获取csrftoken的值 —— 》 request.META[CSRF_COOKIE] 3. process_view 1. 视图函数加上csrf_exempt装饰器不进行CSRF校验
2. 请求方式 是GET, HEAD, OPTIONS, TRACE 也不进行校验
3. csrf_token request.META.get(CSRF_COOKIE) # cookie中获取csrftoken的值# 获取提交的csrfmiddlewaretoken的值request_csrf_token request.POST.get(csrfmiddlewaretoken, )如果或许不到csrfmiddlewaretoken的值再尝试从请求头中获取X_CSRFTOKEN的值 —— 》request_csrf_token4. request_csrf_token 和 csrf_token 进行比较1. 能比较成功 通过校验2. 不能比较成功 拒绝 转载于:https://www.cnblogs.com/Ryan-Yuan/p/11587312.html