Django -- 中间件

中间件

定义

中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。

django中间件是django的门户
1.请求来的时候需要先经过中间件才能到达真正的django后端
2.响应走的时候最后也需要经过中间件才能发送出去

使用步骤

步骤:
1、、先建一个文件夹,里面写一个py文件
2、、然后开始写类
1.中间件就是一个类,类里面写几个方法
class M1(MiddlewareMixin):  必须继承
    def process_request(self,request):  request:请求里面的所有的东西
        print("m1.request_request") 
        这个方法里面别轻易返回值,要是有返回值就不再继续执行后面的了,执行自己的process_response和上边的response
        一般是无返回值的:继续执行后续的中间件和视图函数
    def process_response(self,request,response):
        return response
    
2.在settings中的MIDDLEWARE加上路径    
    文件夹名称.py文件名称.类名
3.找到继承的那个类,吧那个类拿过来
  一般不要用导入的方法,不然有时候更新了就没有这个类了,你就把它继承的那个类拿过来,

自定义中间件

process_request

 1.请求来的时候需要经过每一个中间件里面的process_request方法结果的顺序是按照配置文件中注册的中间件从上往下的顺序依次执行

2.如果中间件里面没有定义该方法,那么直接跳过执行下一个中间件

3.如果该方法返回了HttpResponse对象,那么请求将不再继续往后执行,而是直接原路返回(校验失败不允许访问...)
          

process_response

1.响应走的时候需要结果每一个中间件里面的process_response方法,该方法有两个额外的参数request,response

2.该方法必须返回一个HttpResponse对象
     1.默认返回的就是形参response
     2.你也可以自己返回自己的

3.顺序是按照配置文件中注册了的中间件从下往上依次经过如果你没有定义的话 直接跳过执行下一个
        
研究如果在第一个process_request方法就已经返回了HttpResponse对象,那么响应走的时候是经过所有的中间件里面的process_response还是有其他情况?

是其他情况,就是会直接走同级别的process_reponse返回
        

process_view

1.路由匹配成功之后执行视图函数之前,会自动执行中间件里面的该放法
2.顺序是按照配置文件中注册的中间件从上往下的顺序依次执行

process_template_response

1.返回的HttpResponse对象有render属性的时候才会触发
2.顺序是按照配置文件中注册了的中间件从下往上依次经过

process_exception

1.当视图函数中出现异常的情况下触发
2.顺序是按照配置文件中注册了的中间件从下往上依次经过

csrf跨站请求伪造

如何规避上述问题?

csrf跨站请求伪造校验
网站在给用户返回一个具有提交数据功能页面的时候会给这个页面加一个唯一标识
当这个页面朝后端发送post请求的时候 我的后端会先校验唯一标识,如果唯一标识不对直接拒绝(403 forbbiden)如果成功则正常执行

如何符合校验?

from表单校验方法:{% csrf_token %}

<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>

ajax校验方法:三种

第一种 利用标签查找获取页面上的随机字符串
data{"username":'jason','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()}

第二种 利用模版语法提供的快捷书写
data:{"username":'jason','csrfmiddlewaretoken':'{{ csrf_token }}'}

第三种 通用方式直接拷贝js代码并应用到自己的html页面上即可
data:{"username":'jason'}

例子

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相关装饰器

csrf_protect  需要校验
csrf_exempt   忽视校验

例子

from django.views.decorators.csrf import csrf_protect,csrf_exempt
from django.utils.decorators import method_decorator

@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')

cbv加装饰器

第一种方法:给方法添加

# @method_decorator(csrf_protect)  针对csrf_protect  可以
# @method_decorator(csrf_exempt)  针对csrf_protect  不可以

from django.views import View

class MyCsrfToken(View):
    def get(self,request):
        return HttpResponse('get')

    @method_decorator(csrf_protect)  
    @method_decorator(csrf_exempt) 
    def post(self,request):
        return HttpResponse('post')

第二种方法:给类添加

# @method_decorator(csrf_protect,name='post')  针对csrf_protect  可以

# @method_decorator(csrf_exempt,name='post')  针对csrf_protect  不可以

from django.views import View

@method_decorator(csrf_protect,name='post')  @method_decorator(csrf_exempt,name='post')  class MyCsrfToken(View):

    def get(self,request):
        return HttpResponse('get')

    def post(self,request):
        return HttpResponse('post')

第三种方法:dispatch

# @method_decorator(csrf_protect)  针对csrf_protect  可以

# @method_decorator(csrf_exempt)   针对csrf_exempt 可以

from django.views import View

class MyCsrfToken(View):
    @method_decorator(csrf_protect)  
    @method_decorator(csrf_exempt)  
    def dispatch(self, request, *args, **kwargs):
        return super(MyCsrfToken, self).dispatch(request,*args,**kwargs)

    def get(self,request):
        return HttpResponse('get')

 
    def post(self,request):
        return HttpResponse('post')

 总结

 

posted @ 2020-06-08 21:42  zhw_sylvia  阅读(141)  评论(0编辑  收藏  举报