day56:django:csrf_token&檔案上傳

Poke發表於2020-09-23

目錄

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')