zoukankan      html  css  js  c++  java
  • Django:Csrf

    1.AJAX准备知识

    • 什么是JSON?

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

    • 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字符串
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body>
          <script type="text/javascript">
              var temp = {"name":"刘备"};
              str_temp = JSON.stringify(temp);
              console.log(str_temp);
              console.log(typeof str_temp);
          </script>
      </body>
      </html>
      
      • 显示在网页为字符串

    • parse

      • 将JSON字符串转换为JavaScript对象
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body>
          <script type="text/javascript">
              var temp = '{"name":"曹操"}';
              obj_temp = JSON.parse(temp);
              console.log(obj_temp);
              console.log(typeof obj_temp);
          </script>
      </body>
      </html>
      
      • 显示网页为object对象

    3.JSON与XML比较

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

    4.AJAX

    • AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的JavaScript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。

    • AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

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

    • AJAX不需要任何浏览器插件,但是需要用户允许JavaScript在浏览器执行。

      • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
      • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
    • 示例:页面输入两个整数,通过AJAX传输到后端计算出结果并返回。

    • index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script  src="/static/jquery.js"></script>
    </head>
    <body>
    <input type="text" name="r1">+
    <input type="text" name="r2">=
    <input type="text" name="r3">
    <button id="b1">提交</button>
    <br>
    
        <script type="text/javascript">
            //获取点击事件
            $("#b1").click(function(){
               	//ajax处理:$.ajax({})
                $.ajax({
                    url:"/cla/",//请求url
                    type:"post",//请求方式
                    data:{
                        num1:$("[name='r1']").val(),//获取input值
                        num2:$("[name='r2']").val(),//获取input值
                    },
                    //成功就执行,下面函数。
                    success:function (data) {
                        $("[name='r3']").val(data)
                    }
                })
            })
        </script>
    </body>
    </html>
    
    • 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请求才会顺利执行也就是它:

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

    三种装饰器介绍

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

      #模块导入:
      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
      

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

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

      • 加上装饰器,访问页面

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

    from django.middleware.csrf import CsrfViewMiddleware
    

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

    • 总结

      第一步: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
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="/static/jquery.js"></script>
    </head>
    <body>
        <input type="file" id="f1" name="pic">
        <button id="b">上传</button>
        <p></p>
        <script>
            //触发点击事先
            $("#b").click(function () {
                //新建一个对象
                var formobj = new FormData();
                //往对象添加键值对
                formobj.append("file",document.getElementById("f1").files[0]);
                formobj.append("name","xjk");
                $.ajax({
                    url:"/uploadpic/",
                    type:"post",
                    data :formobj,
                    //processData为True,就会成为URLencode数据,不设置urlencode
                    processData:false,
                    //请求头设置false,不让它自己设置,自己设置就会成为URLencode编码
                    contentType:false,
                    success:function(data){
                        //上传成功给页面提示上传成功
                        $("p").text(data)
                    }
    
                })
            })
        </script>
    </body>
    </html>
    
    #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
      

    方式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(),
                    },
    

    方式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插件。
  • 相关阅读:
    JavaScript对原始数据类型的拆装箱操作
    Javascript继承(原始写法,非es6 class)
    动态作用域与词法作用域
    自行车的保养
    探索JS引擎工作原理 (转)
    C语言提高 (7) 第七天 回调函数 预处理函数DEBUG 动态链接库
    C语言提高 (6) 第六天 文件(续) 链表的操作
    C语言提高 (5) 第五天 结构体,结构体对齐 文件
    C语言提高 (4) 第四天 数组与数组作为参数时的数组指针
    C语言提高 (3) 第三天 二级指针的三种模型 栈上指针数组、栈上二维数组、堆上开辟空间
  • 原文地址:https://www.cnblogs.com/xujunkai/p/11848070.html
Copyright © 2011-2022 走看看