day56:django:csrf_token&文件上傳
- 2020 年 9 月 23 日
- 筆記
- PythonS31-筆記, Python全棧31期-筆記
目錄
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')