Loading

Django之CSRF和AJAX

JSON

什么是 JSON ?

  • JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
  • JSON 是轻量级的文本数据交换格式
  • JSON 独立于语言 *
  • JSON 具有自我描述性,更易理解

* JSON 使用 JavaScript 语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。

img

stringify与parse方法

JavaScript中关于JSON对象和字符串转换的两个方法:

  • JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象 
JSON.parse('{"name":"alex"}');
JSON.parse('{name:"alex"}') ;      // 错误,属性名必须使用双引号
JSON.parse('[18,undefined]') ;     // 错误,不能使用undefined
  • JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。 
JSON.stringify({"name":"alex"})

CSRF

django为用户实现防止跨站请求伪造的功能,通过中间django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

全局:

中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

  • csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。

  • csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

开启csrf后 , 当用post提交数据的时候,django会去检查是否有一个csrf的随机字符串,如果没有就会报错.

通过form提交

在form表单里面需要添加{%csrf_token%}

这样当你查看页面源码的时候,可以看到form中有一个input是隐藏的

1561636459516

当用户访问login页面的时候,会生成一个csrf的随机字符串,,并且cookie中也存放了这个随机字符串,当用户再次提交数据的时候会带着这个随机字符串提交,如果没有这个随机字符串则无法提交成功

cookie中存放的csrftoken如下图

1561636588496

csrf装饰器

from django.views.decorators.csrf import csrf_exempt,csrf_protect,ensure_csrf_cookie

csrf_exempt   #某个视图不需要进行csrf校验上
csrf_protect  #某个视图需要进行csrf校验
ensure_csrf_cookie  #确保生成csrf的cookie

csrf_exempt

csrf_exempt,不能加在类上,也不能加在方法上,只能加在dispatch上

作用:中间件开启csrf校验,针对POST等可通过这个装饰器豁免,不在进行校验

方法一:

class Login(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        ret = super().dispatch(request, *args, **kwargs)
        return ret  

方法二:

@method_decorator(csrf_exempt,name='dispatch')
class Login(View):
    def get(self, request, *args, **kwargs):
        pass
    def post(self, request, *args, **kwargs):
        pass

csrf_protect

当中间件django.middleware.csrf.CsrfViewMiddleware禁用后,可通过csrf_protect开启,可以加在方法上

生成csrftoken的cookie

@method_decorator(ensure_csrf_cookie)
def get(self, request, *args, **kwargs):
    return render(request, 'login.html')

csrf功能

1.csrf中间件中执行process_request:

​ 1. 从cookie中获取到csrftoken的值

​ 2. csrftoken的值放入到 request.META

2.执行process_view

  1. 查询视图函数是否使用csrf_exempt装饰器,使用了就不进行csrf的校验

  2. 判断请求方式:

    1. 如果是GET', 'HEAD', 'OPTIONS', 'TRACE'

      不进行csrf校验

      1. 其他的请求方式(post,put)

      进行csrf校验:

      1.获取cookie中csrftoken的值

      获取csrfmiddlewaretoken的值

      ​ 能获取到 ——》 request_csrf_token

      ​ 获取不到 ——》 获取请求头中X-csrftoken的值 ——》request_csrf_token

      比较上述request_csrf_token和cookie中csrftoken的值,比较成功接收请求,比较不成功拒绝请求。

ajax

1.发请求的方式

1.地址栏输入地址 GET

2.form表单 GET/POST

3.a标签 GET

2.ajax 和 json

  1. json 是各系统,各编程语言间传输数据的一种规定格式

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

    1. 优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
    2. AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。是一个异步的过程
  3. javascript 对 json对象的方法

    JSON.parse(),# 将用于将一个 JSON 字符串转换为 JavaScript 对象 
    	JSON.parse('{"name":"alex"}');
    JSON.stringify(),用于将 JavaScript 值转换为 JSON 字符串。
    	JSON.stringify({"name":"alex"})
    
  4. AJAX 就是使用js的技术发送请求和接受响应的

    特点:

    1.异步的 ,AJAX使用JavaScript技术向服务器发送异步请求;

    2.是局部刷新的,AJAX请求无须刷新整个页面

    3.传输的数据量少,因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高;

3. AJAX常用应用场景

  1. 搜索引擎根据用户输入的关键字,自动提示检索关键字。

  2. 注册时候的用户名的查重。

    • 这里就使用了AJAX技术!当文件框发生了输入变化时,使用AJAX技术向服务器发送一个请求,然后服务器会把查询到的结果响应给浏览器,最后再把后端返回的结果展示出来。

    • 整个过程中页面没有刷新,只是刷新页面中的局部位置而已!

    • 当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应!

    • 当输入用户名后,把光标移动到其他表单项上时,浏览器会使用AJAX技术向服务器发出请求,服务器会查询名为lemontree7777777的用户是否存在

4. jquery 实现ajax请求

注意 : 对于发送给服务器的data数据中,若值不是字符串形式,需要将其转换成字符串类型。

 data:{"i1":$("#i1").val(),"i2":$("#i2").val(),"hehe": JSON.stringify([1, 2, 3])}
先导入jquery.js
$.ajax({
    url: '/calc/',
    type: 'post',
    data: {
        a: $("[name='i1']").val(),
        b: $("[name='i2']").val(),
    },
    success: function (res) {   --->成功接收请求,res就是就收到的项响应体
        $("[name='i3']").val(res)
    },
    error:function (error) {  -->接受失败了的错误信息
        console.log(error)
    }
})

<--ajax上传文件的实现-->
<input type="file" id="f1">
<button id="b1">上传</button>

$('#b1').click(function () {
        var  formobj =  new FormData();
        formobj.append('file',document.getElementById('f1').files[0]);
        // formobj.append('file',$('#f1')[0].files[0]); //添加键值对,值为该文件对象
        formobj.append('name','alex');

        $.ajax({
            url: '/upload/',
            type: 'post',
            data:formobj ,
            processData:false,  // 告诉jQuery不要去处理发送的数据
            contentType:false,  // 告诉jQuery不要去设置Content-Type请求头
            success: function (data) {
                console.log(data)
            },
        })
    })  

    
    //py文件
 def upload(request):
    print(request.FILES)  -->file
    print(request.POST)  -->name
    return render(request,'upload.html')   

5.ajax 通过crsf 的校验

  1. 前提条件 :确保有csrftoken的cookie

    在页面中使用{% crsf_token%}

    加装饰器ensure_crsf_cookie

    from django.views.decorators.csrf import csrf_exempt,csrf_protect,  ensure_csrf_cookie
    
  2. 给data中添加csrfmiddlewaretoken的值,在ajax请求中

    data: {
        'csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val(),
        a: $("[name='i1']").val(),
        b: $("[name='i2']").val(),
    },
    
  3. 或者 --> : 加请求头

    headers:{
        'x-csrftoken':$('[name="csrfmiddlewaretoken"]').val(),
    },
    
  4. 或者 --> : 使用文件

    //ajax_setup.js文件
    //自己写一个getCOOKIE方法
    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');
    
    //每一次都这么写太麻烦了,可以使用$.ajaxSetup()方法为ajax请求统一设置。
    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);
        }
      }
    });
    

    **注意: ** 使用从cookie中取csrftoken的方式,需要确保cookie存在csrftoken值。

    如果你的视图渲染的HTML文件中没有包含 {% csrf_token %},Django可能不会设置CSRFtoken的cookie。这个时候需要使用ensure_csrf_cookie()装饰器强制设置Cookie。

    django.views.decorators.csrf import ensure_csrf_cookie
    
    
    @ensure_csrf_cookie
    def login(request):
        pass
    
posted @ 2019-06-28 19:25  陌路麒麟  阅读(756)  评论(0)    收藏  举报