Django:Csrf

1.AJAX准备知识

  • 什么是JSON?

    • JSON指得是JavaScript对象表示法
    • JSON是轻量级的文本数据交换格式
    • JSON是独立语言
    • JSON具有自我描述性,更容易理解
  • 优势:JSON使用JavaScript语法来描述数据对象,但是JSON仍然独立于语言和平台。JSON解析器和JSON库支持许多不同编程语言。

    Django:Csrf_第1张图片

  • JavaScript支持数据类型:数字型,字符串型,布尔类型,数组类型,对象,null
  • Python支持数据类型:整型浮点型、字符串类型、布尔类型、列表类型、字典类型、None

  • 合格JSON对象输入方式:

    ["one","two","three"]
    {"one":1,"two":2,"three":3}
    {"name":["曹操","刘备","孙权"]}
  • 不合格JSON对象

    {"name":"张三",'age':32}  //属性名必须使用双引号
    [23,44,0xFFF]               //不能使用十六进制
    {"name":Undefined}         //不能使用Undefined
    

2.字符串&&JSON对象转换方法

  • stringify

    • 将JavaScript值转换为JSON字符串
    
    
    
        
        Title
    
    
        
    
    
    • 显示在网页为字符串

      Django:Csrf_第2张图片

  • parse

    • 将JSON字符串转换为JavaScript对象
    
    
    
        
        Title
    
    
        
    
    
    • 显示网页为object对象

      Django:Csrf_第3张图片

3.JSON与XML比较

  • JSON书写简单、层次清晰、易于阅读。符合JavaScript原生语法,可以由解释引擎直接处理,不用另外添加解析代码。

4.AJAX

  • AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的JavaScript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。
  • AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

  • AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)

  • AJAX不需要任何浏览器插件,但是需要用户允许JavaScript在浏览器执行。
    • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
    • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
  • 示例:页面输入两个整数,通过AJAX传输到后端计算出结果并返回。
  • index.html




    
    Title
    


+
=



  • views.py
def index(request):
    return render(request,"index.html")

def cla(request):
    #获取页面值,
    num1 = request.POST.get("num1")
    num2 = request.POST.get("num2")
    print(num1)
    print(num2)
    #相加
    result = int(num1) + int(num2)
    #返回给页面
    return HttpResponse(result)

5.Csrf的那些事情:

  • {%csrf_token%}在页面生成一个隐藏的input标签。

  • 前面操作我们是把settings的MIDDLEWARE的中间件注销掉POST请求才会顺利执行也就是它:

    Django:Csrf_第4张图片

  • 当打开中间件,在点击提交时候会报一个CSRF验证失败,请求终止错误。

Django:Csrf_第5张图片

三种装饰器介绍

  • 首先先介绍三个装饰器:

    #模块导入:
    from django.views.decorators.csrf import csrf_exempt,csrf_protect,ensure_csrf_cookie
    
    #1
    csrf_exempt      某个视图不需要进行csrf校验
    csrf_protect     某个视图需要进行csrf校验
    ensure_csrf_cookie   确保生成csrf的cookie
    
  • csrf_exempt

    • 使用csrf_exempt表示不需要进行CSRF校验,但注意当为CBV时不能加在方法上也不能加类上面,只能加在dispatch上

      ##导入模块csrf用户创建csrf装饰器
      from django.views.decorators.csrf import csrf_exempt,csrf_protect,ensure_csrf_cookie
      from django.utils.decorators import method_decorator
      class Login(View):
          @method_decorator(csrf_exempt)
          def dispatch(self, request, *args, **kwargs):
              ret = super().dispatch(request, *args, **kwargs)
              return ret
      
          def get(self,request,*args,**kwargs):
              return render(request,"login.html")
      
      
          def post(self,request,*args,**kwargs):
              pass
  • csrf_portect

    • 当注释掉setting中间件'django.middleware.csrf.CsrfViewMiddleware',使用装饰器csrf_portect,表示该方法需要校验
    from django.views.decorators.csrf import csrf_exempt,csrf_protect,ensure_csrf_cookie
    from django.utils.decorators import method_decorator
    class Login(View):
        def get(self,request,*args,**kwargs):
            return render(request,"login.html")
    
      @method_decorator(csrf_protect)
        def post(self,request,*args,**kwargs):
            pass

    Django:Csrf_第6张图片

    • post方法需要校验但是,我们没有做校验操作。所以报错
  • ensure_csrf_cookie 确保页面生成csrftoken值,在cookie里

    也可通过不注释掉django.middleware.csrf.CsrfViewMiddleware,网页设置{%csrf_token%}
    
    • 如果注释掉'django.middleware.csrf.CsrfViewMiddleware',

    Django:Csrf_第7张图片

    • 加上装饰器,访问页面

      Django:Csrf_第8张图片

6.中间件django.middleware.csrf.CsrfViewMiddleware的实现(源码分析):

from django.middleware.csrf import CsrfViewMiddleware

Django:Csrf_第9张图片

Django:Csrf_第10张图片

from django.conf import global_settings 可以查看global_settings文件

Django:Csrf_第11张图片

Django:Csrf_第12张图片

Django:Csrf_第13张图片

Django:Csrf_第14张图片

Django:Csrf_第15张图片

Django:Csrf_第16张图片

Django:Csrf_第17张图片

Django:Csrf_第18张图片

Django:Csrf_第19张图片

  • 总结

    第一步:csrf中间件执行process_request做了什么事?
      1.从cookie中获取到csrftoken的值。
      2.csrftoken值放入到request.META中,请求头
    第二步:process_view方法执行又做了什么?
      1.查看视图函数是否使用csrf_exepmt装饰器,使用了就不进行csrf校验
      2.判断请求方式
          如果是GET,HEAD,OPTIONS,TRACE,不进行csrf校验
          如果是其他请求,如POST,PUT,进行CSRF校验
              1.获取cookie中csrftoken的值
              2.POST请求中获取csrfmiddlewaretoken的值:
                  获取到--->request_csrf_token
                  获取不到(如PUT,DELETE请求)--->获取请求头中X-csrftoken的值--->request_csrf_token
    比较上面2个值,比较成功接收请求,比较不成功失败。     

7.ajax的参数和上传文件

#######upload.html



    
    Title
    


    
    
    

#view.py页面
def upload(request):
    return render(request,"upload.html")

def uploadpic(request):
    pic = request.FILES.get("file")
    print(pic)
    print(request.FILES)
    print(request.POST)
    with open("pic.png", 'wb') as f:
        for item in pic.chunks():
            f.write(item)
    return HttpResponse("上传成功")

8.ajax通过django的csrf校验的方法(中间件打开)

  • 之间例题由于注释掉了settings的MIDDLEWARE的中间件,所以才能提交POST请求,这样并不合理。那么如何让AJAX通过csrf校验。

  • AJAX通过csrf的校验的必须要保证csrftoken的cookie

    • 确保csrftoken有cookies有两种方式:
  • 必有{%csrf_token%}

    1.加装饰器:ensure_csrf_cookies,
    2.csrfmiddlewaretoken

Django:Csrf_第20张图片

方式1:

1.在页面使用{%csrf_token%}#加载时候生成input隐形表单
2.打开'django.middleware.csrf.CsrfViewMiddleware',
3.给ajax中添加csrfmiddlewaretoken
data: {
    #获取csrf_token表单的csrfmiddlewaretoken然后提交给服务器
    'csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val(),
    a: $("[name='i1']").val(),
    b: $("[name='i2']").val(),
}

方式2:

#ajax内加入
headers:{
                    "x-csrftoken":$('[name="csrfmiddlewaretoken"]').val(),
                },
    
    
#注意:重新设置CSRF_HEADER_NAME值,也可执行
在setting.py设置
CSRF_HEADER_NAME = "HTTP_ASD"
headers:{
                    "asd":$('[name="csrfmiddlewaretoken"]').val(),
                },

Django:Csrf_第21张图片

方式3:

通过导入JavaScript实现:方式与方式2相似

//ajax_setpu.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;
}
//从本地读取到cookie根据你提供name=csrftoken,获取值。
var csrftoken = getCookie('csrftoken');


function csrfSafeMethod(method) {
  // these HTTP methods do not require CSRF protection
  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
//对全局ajax进行设置,在ajax之前,执行函数。
//在每次发ajax请求前面都要设置请求头X-CSRFToken。
$.ajaxSetup({
  beforeSend: function (xhr, settings) {
    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader("X-CSRFToken", csrftoken);
    }
  }
});
  • 也可以用jquery.cookie.js插件。

你可能感兴趣的:(Django:Csrf)