Django中间件
Django中间件
Django中间件
1、Django中间件是Django的门户
请求来的时候需要先经过中间件才能到达真正的Django后端
响应走的时候最后也需要经过中间件才能发送出去
2、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', ]
3、Django支持程序员自定义中间件并且暴露给程序员五个可以自定义的方法
必须掌握
process_request process_response
了解即可
process_view process_template_response process_exception
自定义中间件
自定义中间件的步骤
1、在项目名或者应用名下创建一个任意名称的文件夹
2、在该文件夹内创建一个任意名称的py文件
3、在该py文件内需要书写类(这个类必须继承MiddlewareMixin),然后在这个类里面就可以自定义五个方法了,五个方法并不是全部都要书写,用几个写几个
4、需要将类的路径以字符串的形式注册到配置文件中才能生效
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', '你自己写的中间件的路径2', '你自己写的中间件的路径3', ]
process_request
1、请求来的时候需要经过每一个中间件里面的process_request方法,经过的顺序是按照配置文件中注册的中间件从上往下的顺序依次执行
2、如果中间件里面没有定义该方法,那么直接跳过执行下一个中间件
3、如果该方法返回了HttpResponse对象,那么请求将不再继续往后执行,而是直接原路返回(校验失败不允许访问...)
process_request方法就是用来做全局相关的所有限制功能
process_response
1、响应走的时候需要经过每一个中间件里面的process_response方法,该方法有两个额外的参数request,response
response就是Django后端返回给浏览器的内容
2、该方法必须返回一个HttpResponse对象
默认返回的就是形参response
你也可以自己返回自己的
3、顺序是按照配置文件中注册了的中间件从下往上依次经过,如果没有定义的话 直接跳过执行下一个
4、如果在第一个process_request方法就已经返回了HttpResponse对象,那么响应走的时候会直接走同级别的process_reponse返回
扩展:Flask框架也有一个中间件但是它的规律,只要返回数据了就必须经过所有中间件里面的类似于process_reponse方法
process_view
路由匹配成功之后执行视图函数之前,会自动执行中间件里面的该放法,顺序是按照配置文件中注册的中间件从上往下的顺序依次执行
process_template_response
返回的HttpResponse对象有render属性的时候才会触发,顺序是按照配置文件中注册了的中间件从下往上依次经过
process_exception
当视图函数中出现异常的情况下触发,顺序是按照配置文件中注册了的中间件从下往上依次经过
代码:
自定义的中间件
视图层
def index(request): print('我是视图函数index') obj = HttpResponse('index') def render(): print('内部的render') return HttpResponse("O98K") obj.render = render return obj
csrf跨站请求伪造
1、关于钓鱼网站简述
我搭建一个跟正规网站一模一样的界面(中国银行);用户不小心进入到了我们的网站,用户给某个人打钱;打钱的操作确确实实是提交给了中国银行的系统,用户的钱也确确实实减少了;但是唯一不同的时候打钱的账户不适用户想要打的账户变成了一个莫名其妙的账户
2、内部本质
我们在钓鱼网站的页面 针对对方账户 只给用户提供一个没有name属性的普通input框,然后我们在内部隐藏一个已经写好name和value的input框
3、如何避免这种情况发生
csrf跨站请求伪造校验
网站在给用户返回一个具有提交数据功能页面的时候会给这个页面加一个唯一标识,当这个页面朝后端发送post请求的时候 我的后端会先校验唯一标识,如果唯一标识不对直接拒绝(403 forbbiden),如果成功则正常执行。
如何实现csrf校验
1、form表单如何符合校验
{% csrf_token %} 在from下面添加这个即可
<form action="" method="post"> {% csrf_token %} <p>username:<input type="text" name="username"></p> <p>target_user:<input type="text" name="target_user"></p> <p>money:<input type="text" name="money"></p> <input type="submit"> </form>
2、Ajax如何符合校验
第一种 利用标签查找获取页面上的随机字符串
data:{"username":'jason','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()},
第二种 利用模版语法提供的快捷书写
data:{"username":'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},
第三种 通用方式直接拷贝js代码并应用到自己的html页面上即可
data:{"username":'jason'}
需拷贝的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); } } });
拷贝导入用就可以
csrf相关装饰器
1、介绍
需要先导入
from django.views.decorators.csrf import csrf_protect,csrf_exempt
csrf_protect 是csrf需要校验
csrf_exempt 是忽视csrf校验
代码
# @csrf_exempt # @csrf_protect def transfer(request): if request.method == 'POST': username = request.POST.get('username') target_user = request.POST.get('target_user') money = request.POST.get('money') print('%s给%s转了%s元'%(username,target_user,money)) return render(request,'transfer.html')
2、CBV使用
csrf_protect 针对csrf_protect符合我们之前所学的装饰器的三种玩法
csrf_exempt 针对csrf_exempt只能给dispatch方法加才有效
from django.utils.decorators import method_decorator from django.views import View # @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')