day70 django中间件
一、django的七个中间件
django中间件是浏览器和服务端交互的第一个门栏,请求来的时候需要通过中间件,响应走的时候也需要进过中间件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware'
from django.middleware.security import 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.security.SecurityMiddleware'
from django.middleware.security import SecurityMiddleware
# 我们可以去这些中间件的源码里去找
class SessionMiddleware(MiddlewareMixin):
def process_request(self, request):
session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
request.session = self.SessionStore(session_key)
def process_response(self, request, response):
return response
class CsrfViewMiddleware(MiddlewareMixin):
def process_request(self, request):
csrf_token = self._get_token(request)
if csrf_token is not None:
# Use same token next time.
request.META['CSRF_COOKIE'] = csrf_token
def process_view(self, request, callback, callback_args, callback_kwargs):
return self._accept(request)
def process_response(self, request, response):
return response
class AuthenticationMiddleware(MiddlewareMixin):
def process_request(self, request):
request.user = SimpleLazyObject(lambda: get_user(request))
'''
django支持程序员自定义中间件,并且有五个可以自定义的方法
1 必须掌握
process_request
prpcess_respone
2 了解即可
process_view
processs_template_respone
process_exception
'''
二、如何自定义中间件
1 自定义中间件的创建方式
- 先再项目下或者应用下创建一个任意名称的文件夹
- 在项目文件下内创建一个任意名称的py文件
- 在该py文件内书写类,这个类必须继承MiddlewareMixin,然后在这个类中自定制我们的需要的django提供的五个方法,用什么写什么,没有必须要写的
- 将类的路径以字符串的形式注册到配置文件中生效
2 django提供自定制中间件的五个方法
2.1 必须掌握两个方法
process_request
特点:
- 所有请求来到服务端的时候先要依次(按照书写顺序的先后)经过所有中间件的process_request方法(没有就跳过)
- 如果这个函数返回了一个HttpRespone对象,那么这个请求就会从这个函数开始原路返回(会先执行同中间件的process_respone,再依次往上返回)
- 这些特点可以让这个方法作为全局相关的所有限制功能
class Mymid1(MiddlewareMixin):
def process_request(self,request):
print('我是第一个中间件的process_request')
process_response
特点:
- 所有响应返回的时候都要依次(与书写顺序相反)经过所有中间件的process_response方法(没有就跳过)
- 必须返回respons对象
- 返回的相当于是应该响应的数据
- 或者返回一个HttpResponse对象
- 返回的相当于是把应该相应的数据替换成我们自己写的数据(偷梁换柱)
ps:flask也有中间件,它的规律是只要返回了数据就必须要经过所有中间件里类似process_response方法
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,HttpResponse
class Mymid1(MiddlewareMixin):
def process_request(self,request):
print('我是第一个中间件的process_request')
def process_response(self,request,response):
print('我是第一个中间件的process_respone')
return HttpResponse('123') # 截胡
class Mymid2(MiddlewareMixin):
def process_request(self,request):
print('我是第二个中间件的process_request')
def process_response(self, request, response):
print('我是第二个中间件的process_respone')
return response # 正常返回
2.2 了解方法
process_view
- 在路由匹配成功之后,执行视图函数之前会执行此方法
- 所以只会在请求的时候执行
- 执行顺序是中间件从上往下
def process_view(self,request,view_name,args,kwargs):
# print(view_name,args,kwargs)
print('我是第一个中间件的process_view')
process_template_response
- 当视图函数返回的HttpRespone对象中有render属性的时候会触发
- 执行顺序是中间件从下往上
# 中间件中
def process_template_response(self, request, response):
print('我是第二个中间件的process_template_response')
return response
# 视图函数中
def index(request):
print('我是视图函数index')
obj = HttpResponse('index')
def render():
print('内部的render')
return HttpResponse("O98K")
obj.render = render
return obj
process_exception
- 当视图函数出现异常的时候触发(比如写了一个名字但是没定义)
- 顺序按照中间件从下往上
def process_exception(self, request, exception):
print('我是第二个中间件的process_exception')
print(exception) # 报错信息
三、csrf跨站请求伪造校验
1 案例及解决方案
案例:钓鱼网站
用户在一个缴费钓鱼网站给自己制定的用户转钱,结果转到了另一个人账号上
原因:
用户在打开缴费钓鱼网站的时候不会发现区别,钓鱼网站的页面会做的和正规页面一模一样,唯一的区别就是钓鱼网站内部有一个隐藏的input框去代替我们输入的对方账号的input框,最后向缴费服务端发送数据的时候,提交的是隐藏的数据。
如何避免上述问题
解决方案:csrf跨站请求伪造校验
原理:当页面朝后端发送post请求的时候,会顺带发送一个唯一标识码,这个唯一标识码是在渲染页面的时候服务端给页面的数据,如果唯一标识不对,直接拒绝访问(403 forbbiden),如果成功则正常执行
2 如何符合校验
form表单符合校验代码
<form action="" method="post">
{% csrf_token %}
<input type="submit">
</form>
ajax符合校验代码
{% csrf_token %}
<button id="d1">提交</button>
// 方式三:推荐使用,导入一个写好的js文件去自动获取csrf
{% load static %}
<script src="{% static 'js/mysetup.js' %}"></script>
<script>
$('#d1').click(function () {
$.ajax({
url:'',
type:'post',
// 方式一:利用标签获取页面上的验证码
data:{'username':'hz','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()},
// 方式二:利用模版语言便捷写法
data:{'username':'hz','csrfmiddlewaretoken':{% csrf_token %}},
data:{'username':'hz'},
success:function () {
}
})
})
</script>
mysetup.js代码
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
3 相关装饰器
'''
以下两种情况用到两种不同的装饰器
1 网站整体都不校验csrf,就单独几个视图函数需要校验
2 网站整体都不校验csrf,就单独几个视图函数不校验
'''
from django.views.decorators.csrf import csrf_protect,csrf_exempt
'''
csrf_protect:需要校验,在CBV种三种装饰器方法都可以使用
csrf_exempt:忽视校验,在CBV中只能使用给dispatch加装饰器的方法
'''
@csrf_exempt
@csrf_protect
def index(request):
print('我是index函数')
# print(index)
if request.method=='POST':
print(request.POST.get('username'))
return HttpResponse('post index')
return render(request,'index.html')
# CBV
# @method_decorator(csrf_protect,name='post') # 针对csrf_protect 第二种方式可以
# @method_decorator(csrf_exempt,name='post') # 针对csrf_exempt 第二种方式不可以
@method_decorator(csrf_exempt,name='dispatch')
class MyCsrfToken(View):
# @method_decorator(csrf_protect) # 针对csrf_protect 第三种方式可以
# @method_decorator(csrf_exempt) # 针对csrf_exempt 第三种方式可以
def dispatch(self, request, *args, **kwargs):
return super(MyCsrfToken, self).dispatch(request,*args,**kwargs)
def get(self,request):
return HttpResponse('get')
# @method_decorator(csrf_protect) # 针对csrf_protect 第一种方式可以
# @method_decorator(csrf_exempt) # 针对csrf_exempt 第一种方式不可以
def post(self,request):
return HttpResponse('post')
四、重要补充知识点
补充
# 通过一个模块实现和settins的中间件一样以字符串形式导入模块
# 这个方法最小只能到py文件名
import importlib
res = 'myfile.b'
# 下面等价于:from myfile import b
ret = importlib.import_module(res)
思想
利用已学习的知识模仿django中间件导入
# 创建一个包里面存有我们要使用的类
# mymid.qq
class QQ():
def __init__(self):
pass
def send(self,msg):
print(f'qq:{msg}')
# mymid.wechat
class Wechat():
def __init__(self):
pass
def send(self,msg):
print(f'wechat:{msg}')
# 创建一个settings去存储这些类的路径
# settings.py
MYMID_DIR = [
'mymid.qq.QQ',
'mymid.wechat.Wechat',
]
# 重点!!!!!!
# mymid.__init__.py
import importlib
import settings
def send_all(msg):
for mymid in settings.MYMID_DIR:
# 1 先用切片的方式获取模块路径和具体类名
module_path,cls_name = mymid.rsplit('.',maxsplit=1)
# print(module_path,cls_name)
# 2 通过importlib模块以字符串的形式导入指定模块
res = importlib.import_module(module_path)
# 3 通过反射的方法获取类名
cls = getattr(res,cls_name)
obj = cls()
# 4 利用鸭子类型直接调用send方法
obj.send(msg)
# start.py启动文件
import mymid
mymid.send_all('吃饭了')
day70 django中间件的更多相关文章
- Django数据操作F和Q、model多对多操作、Django中间件、信号、读数据库里的数据实现分页
models.tb.objects.all().using('default'),根据using来指定在哪个库里查询,default是settings中配置的数据库的连接名称. 外话:django中引 ...
- django 中间件
django处理一个Request的过程是首先通过django 中间件,然后再通过默认的URL方式进行的.所以说我们要做的就是在django 中间件这个地方把所有Request拦截住,用我们自己的方式 ...
- day20 FORM补充(随时更新),F/Q操作,model之多对多,django中间件,缓存,信号
python-day20 1.FROM生成select标签的数据应该来源于数据库. 2.model 操作 F/Q (组合查询) 3.model 多对多操作. 4.中间件 :在请求到达url前先会经过 ...
- Django学习之七:Django 中间件
目录 Django 中间件 自定义中间件 - - - 大体两种方式 将中间件移除 实例 中间件加载源码阅读 总结 Django 中间件 Tips: 更新日志: 2019.01.31 更新django中 ...
- Django中间件的使用
Django中间件的使用 中间件(middleware) 中间件应用于request与服务端之间和服务端与response之间,客户端发起请求到服务端接收可以通过中间件,服务端返回响应与客户端接收响应 ...
- Django中间件 及 form 实现用户登陆
Django中间件 及 form 实现用户登陆 Form 验证 密码调用md5 加密存储 form.add_error("字段名", "错误信息") 自定义错误 ...
- Django 2.0 学习(20):Django 中间件详解
Django 中间件详解 Django中间件 在Django中,中间件(middleware)其实就是一个类,在请求到来和结束后,Django会根据自己的规则在合适的时机执行中间件中相应的方法. 1. ...
- Django中间件的5种自定义方法
阅读目录(Content) Django中间件 自定义中间件 中间件(类)中5种方法 中间件应用场景 回到顶部(go to top) Django中间件 在http请求 到达视图函数之前 和视图函 ...
- Python自动化之Django中间件
django中间件 Django请求生命周期 中间件中可以定义方法,分别是 process_request(self,request) process_view(self, request, call ...
随机推荐
- MyBatis运行流程及入门第一个程序
1. mybatis是什么? MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并 ...
- 04.Java基础语法
一.Java源程序结构与编程规范 一个完整的Java源程序应该包含下列部分 package语句,至多一句,必须放在源程序第一句 import语句,没有或者若干句,必须放在所有类定义前 public c ...
- 🧑🏻💻数据库简介及Mac平台环境搭建🧑🏻💻
数据库 存储数据的演变过程 如果没有使用数据库,我们自己存放文件,数据格式是千差万别的,完全取决于我们自己,例如: """ # 张三 zhangsan|123|read ...
- idea针对有外联jar包的项目如何编译成可运行的jar包
1.打开file-->project structure 2.如下图所示,创建 3.在空白处右键点击“create directory”创建一个“”“libs”文件夹 4.把项目所需的jar吧, ...
- Nested Report_FR
设置好下面的关系(Mar 18做,copy from MyQ): 1) Customer.Orders.Items 的 MasterSouce.MasterField2) 后面2个的 DataSour ...
- 容器技术之Docker资源限制
上一篇我们聊到了docker容器的单机编排工具docker-compose的简单使用,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13121678.html: ...
- 一个简单的Shell脚本(解决windows上文本在macos上乱码问题)
之所以有这一篇文章,是因为之前我写过的一篇文章:“解决Mac上打开txt文件乱码问题”:传送门: https://www.cnblogs.com/chester-cs/p/11784079.html ...
- 自由切换 网页上的 ico 图标
自由切换 网页上的 ico 图标: 第一步: 进入这个网站 :https://www.uupoop.com/ico/?action=make 第二步: 进入网站后,然后选择 ...
- 黎活明8天快速掌握android视频教程--16_采用SharedPreferences保存用户偏好设置参数
SharedPreferences保存的数据是xml格式,也是存在数据保存的下面四种权限: 我们来看看 我们来看看具体的业务操作类: /** * 文件名:SharedPrecences.java * ...
- JNI通过线程c回调java层的函数
1.参看博客:http://www.jianshu.com/p/e576c7e1c403 Android JNI 篇 - JNI回调的三种方法(精华篇) 2.参看博客: JNI层线程回调Java函数关 ...