zoukankan      html  css  js  c++  java
  • 初谈dango的post提交csrf设置和文件上传

    一、CSRF

    在django中配置了中间件CsrfViewMiddleWare,每次post请求都post请求的话,都需要在form表单中加入{{ csrf_token }},它的运行原理是

    在form表单中生成一个隐藏的input标签

     在post的请求头中把csrftoken加入cookie中

     从上图可以看出来,两个键值对都不相同,验证的原理是:

    cookie是保存在浏览器本地的获取之后时是不会变化的,而隐藏在form表单中的csrfmiddlewaretoken是每次请求都会发生变化的,但是在server端解出来的secret是一致的就表示csrf验证通过。

    post请求使用form表单提交数据比较简单只需要在form中加入{% csrf_token %},POST请求使用Ajax提交时使用 以下的方法

    方法1:

      通过获取隐藏的input标签中的csrfmiddlewaretoken值放在data发送。

    from django.shortcuts import render,HttpResponse
    from django.http import JsonResponse
    
    def index(request):
        if request.method == 'GET':
            return render(request,'login.html')
        else:
            csrf = request.POST.get('csrfmiddlewaretoken')
            return HttpResponse(csrf)
    views.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form method="post" action="/login/">
            <!--必须加上这个应该这个还有Ajax的值是从这个获取的,并且POST的cookie携带csrftoken也是这个的作用-->
            {% csrf_token %}
            <input id="id_username" type="text" name="username">
            <input id="id_password" type="password" name="password">
            <input id="id_button" type="button" value="button">
        </form>
    <script src="/static/jquery-2.1.4.min.js"></script>
    <script>
        $("#id_button").click(function () {
            $.ajax({
            url:'/login/',
            data:{'csrfmiddlewaretoken':$("[name='csrfmiddlewaretoken']").val()},
            type:"POST",
            success:function (arg) {
                alert(arg);
            }
        })
        })
    
    </script>
    </body>
    </html>
    login.html

    注意form标签中的{% csrf_token %}不能删除。

    方法2:

      在Ajaxsetup配置提交,只需在AjaxSetup中配置

     $.ajaxSetup({
            data: {csrfmiddlewaretoken: '{{ csrf_token }}'},
        });
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form method="post" action="/login/">
        <!--必须加上这个应该这个还有Ajax的值是从这个获取的,并且POST的cookie携带csrftoken也是这个的作用-->
        {% csrf_token %}
        <input id="id_username" type="text" name="username">
        <input id="id_password" type="password" name="password">
        <input id="id_button" type="button" value="button">
    </form>
    <script src="/static/jquery-2.1.4.min.js"></script>
    <script>
        // 第二种方式
        $.ajaxSetup({
            data: {csrfmiddlewaretoken: '{{ csrf_token }}'},
        });
        $("#id_button").click(function () {
            $.ajax({
                url: '/login/',
                // data:{'csrfmiddlewaretoken':$("[name='csrfmiddlewaretoken']").val()},
                type: "POST",
                success: function (arg) {
                    alert(arg);
                }
            })
        })
    
    </script>
    </body>
    </html>
    login.html

    方式3:

      前端也能操作后端返回的cookies,所获取响应头中的cookies中csrftoken字段的值放在响应头中,操作cookies需要引入jquery.cookie.js插件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form method="post" action="/login/">
        <input id="id_username" type="text" name="username">
        <input id="id_password" type="password" name="password">
        <input id="id_button" type="button" value="button">
    </form>
    <script src="/static/jquery-2.1.4.min.js"></script>
    <script src="/static/jquery.cookie.js"></script>
    <script>
    
        $("#id_button").click(function () {
            $.ajax({
                url: '/login/',
                // data:{'csrfmiddlewaretoken':$("[name='csrfmiddlewaretoken']").val()},
                type: "POST",
                // 第三种方式在请求头中,这个直接从响应的中获取cookie所以不需要设置{% csrf_token %}
                headers: {"X-CSRFToken": $.cookie('csrftoken')},
                success: function (arg) {
                    alert(arg);
                }
            })
        })
    
    </script>
    </body>
    </html>
    login.html

    这个是通过响应中的cookies获取csrftoken字段的值提交的,所以不需要{% csrf_token %}配置

    注意在请求头中为键为“X-CSRFToken”

    每个Ajax请求都要设置头不方便,可以设置一个通用头信息,就可以不用每次都在Ajax请求的头里面配置了

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form method="post" action="/login/">
        {% csrf_token %}
        <input id="id_username" type="text" name="username">
        <input id="id_password" type="password" name="password">
        <input id="id_button" type="button" value="button">
    </form>
    <script src="/static/jquery-2.1.4.min.js"></script>
    <script src="/static/jquery.cookie.js"></script>
    <script>
        var csrftoken = $.cookie('csrftoken');
        function csrfSafeMethod(method) {
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
        }
        $.ajaxSetup({
            beforeSend: function (xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        });
        $("#id_button").click(function () {
            $.ajax({
                url: '/login/',
                type: "POST",
                success: function (arg) {
                    alert(arg);
                }
            })
        })
    </script>
    </body>
    </html>
    login.html

    注意,这里如果不配置{% csrf_token %}响应头里面不会有set-cookie,发送post的请求里面也就没有csrftoken的值,但是方式三种且不需要配置{% csrf_token %}不知道是什么原因 。

     二、文件的上传

      讲文件的上传之前,需要先了解一下啊请求头的ContentType的类型

    2.1、contentType类型

      1 application/x-www-form-urlencoded

      这是最常见的POST提交数据的方式。浏览器的原生<form>表单默认使用的就是这中类型

     默认的form表单提交数据请求头是application,响应头是text/html的格式

     在server端解析出的数据

     

     multipart/form-data 这个是文件通过原生的form表单上传的时候设置了enctype/multipart/form-data时请求头的信息

     ajax发送数据,Ajax默认请求头是application,响应头是text/html的类型,和原生form提交数据是一样的,但是Ajax可以配置为其他的类型

    Ajax配置contentType为JSON格式

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form >
        {% csrf_token %}
        <input type="file" name="aabb">
        <input id="id_username" type="text" name="username">
        <input id="id_password" type="password" name="password">
        <input id="id_button" type="button" value="submit">
    
    </form>
    <script src="/static/jquery-2.1.4.min.js"></script>
    <script src="/static/jquery.cookie.js"></script>
    <script>
    
        $("#id_button").click(function () {
            $.ajax({
                url: '/login/',
                // data:{'csrfmiddlewaretoken':$("[name='csrfmiddlewaretoken']").val()},
                type: "POST",
                // 配置为JSON发送的就是JSON字符串了
                contentType:'JSON',
                data:JSON.stringify({'username':$("#id_username").val(),'password':$("#id_password").val()}),
                // data:{'username':$("#id_username").val(),'password':$("#id_password").val()},
                // 第三种方式在请求头中,这个直接从响应的中获取cookie所以不需要设置{% csrf_token %}
                headers: {"X-CSRFToken": $.cookie('csrftoken')},
                success: function (arg) {
                    alert(arg);
                }
            })
        })
    
    </script>
    </body>
    </html>
    login.html
    from django.shortcuts import render,HttpResponse
    from django.http import JsonResponse
    
    def index(request):
        if request.method == 'GET':
            return render(request,'login.html')
        else:
    
            csrf = request.POST.get('csrfmiddlewaretoken')
            print(csrf)
            username=request.POST.get('username')
            print(request.POST.get('username'))
            
            print('POST',request.POST)
            print('body',request.body)
            return HttpResponse(username)
    views.py

     server端收到的也为JSON字符串,并且因为reques.POST无法解析JSON数据打印为一个空列表

    基于form表单的文件上传

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="/login/" enctype="multipart/form-data" method="post">
        {% csrf_token %}
        <input type="file" name="aabb">
        <input id="id_username" type="text" name="username">
        <input id="id_password" type="password" name="password">
        <input id="id_button" type="submit" value="submit">
    
    </form>
    <script src="/static/jquery-2.1.4.min.js"></script>
    <script src="/static/jquery.cookie.js"></script>
    <!--<script>-->
    
        <!--$("#id_button").click(function () {-->
            <!--$.ajax({-->
                <!--url: '/login/',-->
                <!--// data:{'csrfmiddlewaretoken':$("[name='csrfmiddlewaretoken']").val()},-->
                <!--type: "POST",-->
                <!--// 配置为JSON发送的就是JSON字符串了-->
                <!--contentType:'JSON',-->
                <!--data:JSON.stringify({'username':$("#id_username").val(),'password':$("#id_password").val()}),-->
                <!--// data:{'username':$("#id_username").val(),'password':$("#id_password").val()},-->
                <!--// 第三种方式在请求头中,这个直接从响应的中获取cookie所以不需要设置{% csrf_token %}-->
                <!--headers: {"X-CSRFToken": $.cookie('csrftoken')},-->
                <!--success: function (arg) {-->
                    <!--alert(arg);-->
                <!--}-->
            <!--})-->
        <!--})-->
    
    <!--</script>-->
    </body>
    </html>
    login.html
    from django.shortcuts import render,HttpResponse
    from django.http import JsonResponse
    import json,os
    from django.conf import settings
    
    def index(request):
    
        if request.method == 'GET':
            return render(request,'login.html')
        else:
    
            csrf = request.POST.get('csrfmiddlewaretoken')
            print(csrf)
            username=request.POST.get('username')
            print(request.POST.get('username'))
            #原始数据
            # print('body',request.body)
            print('POST',request.POST)
            print('files',request.FILES)
            #保存文件
            #获取文件对象
            file_obj = request.FILES.get('aabb')
            file_name = file_obj.name  #获取文件名
            #不设置目录保存在根目录下
            path=os.path.join(settings.BASE_DIR, 'media', 'img')
            if not os.path.exists(path):
                os.makedirs(path)
            with open(f'{path}//{file_name}', 'wb') as f:
                for chunks in file_obj.chunks():
                    f.write(chunks)
            return HttpResponse(username)
    views.py

    server接受的数据部分

     ajax上传文件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form>
        {% csrf_token %}
        <input  id="id_file" type="file" name="aabb">
        <input id="id_username" type="text" name="username">
        <input id="id_password" type="password" name="password">
        <input id="id_button" type="button" value="submit">
    
    </form>
    <script src="/static/jquery-2.1.4.min.js"></script>
    <script src="/static/jquery.cookie.js"></script>
    <script>
    
        $("#id_button").click(function () {
            var formdata = new FormData();
            formdata.append('username',$("#id_username").val());
            formdata.append('password',$("#id_password").val());
            formdata.append('aabb',$("#id_file")[0].files[0]);
            $.ajax({
                url: '/login/',
                type: "POST",
                data:formdata, //将添加好数据的formdata放到data这里
                processData: false ,    // 不处理数据
                contentType: false,    // 不设置内容类型
                // 第三种方式在请求头中,这个直接从响应的中获取cookie所以不需要设置{% csrf_token %}
                headers: {"X-CSRFToken": $.cookie('csrftoken')},
                success: function (arg) {
                    alert(arg);
                }
            })
        })
    
    </script>
    </body>
    </html>
    login.html
    from django.shortcuts import render,HttpResponse
    from django.http import JsonResponse
    import json,os
    from django.conf import settings
    
    def index(request):
    
        if request.method == 'GET':
            return render(request,'login.html')
        else:
    
            csrf = request.POST.get('csrfmiddlewaretoken')
            print(csrf)
            username=request.POST.get('username')
            print(request.POST.get('username'))
            #原始数据
            # print('body',request.body)
            print('POST',request.POST)
            print('files',request.FILES)
            #保存文件
            #获取文件对象
            file_obj = request.FILES.get('aabb')
            file_name = file_obj.name  #获取文件名
            #不设置目录保存在根目录下
            path=os.path.join(settings.BASE_DIR, 'media', 'img')
            if not os.path.exists(path):
                os.makedirs(path)
            with open(f'{path}//{file_name}', 'wb') as f:
                for chunks in file_obj.chunks():
                    f.write(chunks)
            return HttpResponse(username)
    views.py
    人生苦短,我用cnblog
  • 相关阅读:
    Python 读取Excel之xlrd篇
    Python读取文件基本方法
    Python 偏函数用法全方位解析
    如何表示只有一个元素的元祖
    Python对文本读写的操作方法【源码】
    jvm入门及理解(六)——垃圾回收与算法
    jvm入门及理解(五)——运行时数据区(虚拟机栈)
    jvm入门及理解(四)——运行时数据区(堆+方法区)
    jvm入门及理解(三)——运行时数据区(程序计数器+本地方法栈)
    jvm入门及理解(二)——类加载器子系统
  • 原文地址:https://www.cnblogs.com/wuzhibinsuib/p/13069263.html
Copyright © 2011-2022 走看看