day56:django:csrf_token&文件上传

目录

1.csrf介绍

2.django实现csrf_token认证

3.django实现文件上传

csrf介绍

什么是csrf?

csrf:跨站请求伪造。攻击者通过HTTP请求将数据传送到服务器,从而盗取会话的cookie。

盗取会话cookie之后,攻击者不仅可以获取用户的信息,还可以修改该cookie关联的账户信息。

django实现csrf_token认证

1.form表单实现csrf_token认证

直接写上{% csrf_token %}

<form action="">
    {% csrf_token %}
    <input type="text" name="username">
    <input type="submit">
</form>

2.ajax实现csrf_token认证

方式1

在html里,写了个{% csrf token %},其实翻译过来,就是生成了个input标签

input标签是这个样子的:

<input type=”hidden” name=”csrfmiddlewaretoken” value=”BzOzpsnD1zqiZMm3jp1TdW2knEI2BvxwEXrsJbZTIdqL1Kj6P7o4pN38sTn8K5ia”>

我们在js中获取属性name为csrfmiddlewaretokan的那个input标签的value的值

然后通过ajax中的data传递过去

// 方式1 
<input type="text" name="username">
<button id="btn">确认</button>

{% csrf_token %}

<script src="{% static 'plugins/jquery.js' %}"></script>
<script>

    var uname = $('#username').val();
    // 方式1
    // 通过input标签的name属性获取csrfmiddlewaretoken的值
    var token = $('[name="csrfmiddlewaretoken"]').val();

    $.ajax({
        url:'/ajax_login',
        type:'post',
        data:{uname:uname,csrfmiddlewaretoken:token}
        success:function (res) {
            alert(res)
        }
    })
</script>

方式2

这种方式和方式1差不多,只是在data中csrfmiddlewaretoken的值 变成了{{ csrf_token }} 

在django中可以通过双大括号取值

<input type="text" name="username">
<button id="btn">确认</button>

{% csrf_token %}



<script src="{% static 'plugins/jquery.js' %}"></script>

<script>

    var uname = $('#username').val();

    $.ajax({
        url:'/ajax_login',
        type:'post',
        // 方式2
        // 直接拿到csrfmiddlewaretoken中value属性对应的值
        data:{uname:uname,csrfmiddlewaretoken:'{{ csrf_token }}'},
        success:function (res) {
            alert(res)
        }
    })

</script>

方式3

data里不在写csrfmiddlewaretoken,而是写在ajax中的header里

这种方法的csrf认证是写在cookie里的 cookie里的csrf和input标签里value的csrf是不一样的

<input type="text" name="username">
<button id="btn">确认</button>

{% csrf_token %}



<script src="{% static 'plugins/jquery.js' %}"></script>

<script>

    var uname = $('#username').val();

    $.ajax({
        url:'/ajax_login',
        type:'post',
        data:{uname:uname},
        headers:{
            'X-CSRFToken':$.cookie('csrftoken') // 这个csrftoken是cookie中的csrftoken,并非csrfmiddlewaretoken的值,两者本身是同一个之,但是二者的加密方式不同,所以加密出来的结果不相同
        },
        success:function (res) {
            alert(res)
        }
    })

</script>

django实现文件上传

1.form表单实现文件上传

<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}

    用户名:<input type="text" name="username" >

    <!-- type类型设置为file,multiple代表可以上传多个文件 -->
    头像:<input type="file" name="avatar" multiple> 

    <input type="submit">

</form>

2.ajax实现文件上传

从html获取数据,在js中获取定义成变量

然后放到formdata中

在ajax中的data直接传formdata即可,注意加processData和ContentType

用户名:<input type="text" name="username" id="username">

头像:<input type="file" name="avatar" id="avatar">
<button id="ajax_btn">上传</button>

<script>
    $('#ajax_btn').click(function () {

        var uname = $('#username').val();
        var file_obj = $('#avatar')[0].files[0]; // 文件对象

        var formdata = new FormData(); // 创建formdata对象,用来获取表单数据,方便进行提交数据
        formdata.append('username',uname); // 获取input框输入的用户名
        formdata.append('csrfmiddlewaretoken','{{ csrf_token }}'); // 获取csrf_token值
        formdata.append('avatar',file_obj); // 获取用户上传的文件对象


        $.ajax({
            url:'/login/',
            type:'post',
            data:formdata, 
            processData: false ,    // 不处理数据
            contentType: false,    // 不设置内容类型
            success:function (res) {
                console.log(res);
            }
        })
    })
</script>

3.文件上传的views.py(form表单和ajax都用这套视图函数)

通过request读取在前端js定义好的file_obj

然后通过文件对象.name 取出文件名 为接下来with open操作做准备

with open(文件名….)打开文件

for循环文件对象 将文件内容写入其他地方

def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    else:
        file_obj = request.FILES.get('avatar')
        name = file_obj.name
        with open(name, 'wb') as f:
            # 方式1
            # for i in file_obj:  # \r\n
# 方式2 # for i in file_obj.chunks(): # \r\n for i in file_obj.chunks(): # \r\n 读取65536B f.write(i) return HttpResponse('ok')