主要內容:https://www.cnblogs.com/maple-shaw/articles/9524153.htmlhtml
1 csrf中間件: csrf跨站請求僞造python
a : crsf的兩個靜態方法:jquery
csrf_exempt : 給單個視圖排除校驗ajax
csrf_protect: 給單個視圖必須校驗數據庫
from django.views.decorators.csrf import csrf_exempt, csrf_protect # 能夠經過csrf校驗, 不註銷csrf插件的狀況下 # @csrf_exempt # def login(request): # return render(request, 'login.html') # 給csrf設置了一層安全保證, 不容許經過 @csrf_protect def login(request): return render(request, 'login.html')
b : csrf的請求流程:django
從process_request方法: 從請求的cookie中獲取csrf_token ——》csrf_token ——》request.META['CSRF_COOKIE']編程
從process_view方法:json
1: 若是視圖函數加上了csrf_exempt的裝飾器,則不作校驗後端
2 : 若是請求方式是'GET', 'HEAD', 'OPTIONS', 'TRACE' 也不作校驗瀏覽器
3 : 其餘的方式作校驗:
request.META.get('CSRF_COOKIE') —— 》 csrf_token
request_csrf_token = ''
# 從request.POST中獲取csrfmiddlewaretoken對應的值
request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
# 從請求頭中獲取X-csrftoken 的值
request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')
request_csrf_token 和 csrf_token 作對比
若是校驗成功 正常走
若是校驗不成功 拒絕
2 瀏覽器向服務器發請求的方式
a : 地址欄上輸入地址 回車, get請求
b : form表單提交數據, 點擊submit, post請求
c : a標籤
d : ajax
3 JSON內容的複習:
在JavaScript中: 關於json對象和字符串轉換的兩個方法:
JSON.parse(): 用於將一個json字符串轉爲JavaScript對象
JSON.stringify(): 用於將JavaScript的值轉換爲json字符串
4 ajax : 一個與服務器進行交互的技術
a : 簡介: 異步的JavaScript和XML, 即便用JavaScript語言與服務器進行異步交互, 傳輸的數據爲XML,(也不僅是xml), 不是一種新的編程語言, 而是一種使用現有的標準的新方法.
b : 優勢
1 : 最大的優勢是在不從新加載整個頁面的狀況下,能夠與服務器交換數據並更新部分網頁內容。(這一特色給用戶的感覺是在不知不覺中完成請求和響應過程)
2 : 異步交互:客戶端發出一個請求後,無需等待服務器響應結束,就能夠發出第二個請求
總結:
AJAX使用JavaScript技術向服務器發送異步請求;
AJAX請求無須刷新整個頁面;
由於服務器響應內容再也不是整個頁面,而是頁面中的部份內容,因此AJAX性能高;
c : 實例: 頁面輸入兩個整數, 經過ajax傳輸到後端進行計算出結果,返回.
url中的代碼:
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/', views.index), url(r'^calc/', views.calc), url(r'^calcs/', views.calcs), ]
views中的代碼:
from django.shortcuts import render, HttpResponse def index(request): i1, i2, i3 = '', '', '' if request.method == 'POST': i1 = int(request.POST.get('i1')) i2 = int(request.POST.get('i2')) i3 = i1 + i2 return render(request, 'index.html', {'i1':i1, 'i2': i2, 'i3': i3}) import time def calc(request): print(request.POST) i1 = int(request.POST.get('i1')) i2 = int(request.POST.get('i2')) i3 = i1 + i2 time.sleep(5) return HttpResponse(i3) def calcs(request): i1 = request.POST.get('i1') i2 = request.POST.get('i2') i3 = i1 + i2 return HttpResponse(i3)
html中的代碼
<body> <input type="text" name="i1">+ <input type="text" name="i2" >= <input type="text" name="i3"> <button id="b1">計算</button> <hr> <input type="text" name="ii1">+ <input type="text" name="ii2" >= <input type="text" name="ii3"> <button id="b2">計算</button> <script src="/static/jquery-3.3.1.min.js"></script> <script> $('#b1').click(function () { $.ajax({ url:'/calc/', type:'post', data:{ i1 : $('[name="i1"]').val(), i2 : $('[name="i2"]').val(), }, success:function (ret) { console.log(ret); $('[name="i3"]').val(ret) } }) }); $('#b2').click(function () { $.ajax({ url:'/calcs/', type:'post', data:{ i1 : $('[name="ii1"]').val(), i2 : $('[name="ii2"]').val(), }, success:function (ret) { console.log(ret); $('[name="ii3"]').val(ret) } }) }); </script> </body> </html>
d : ajax發post請求, 經過csrf驗證的三種方法:
1: 頁面中使用{% csrf_token%}
$('#b1').click(function () {
$.ajax({
url: '/csrf_test/',
type: 'post',
data: {
csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val(), # **********
name: 'alex',
age: '73',
},
success: function (res) {
console.log(res);
}
})
});
2 : 經過獲取返回的cookie中的字符串 放置在請求頭中發送。
$('#b1').click(function () { $.ajax({ url: '/csrf_test/', type: 'post', headers: {"X-CSRFToken": $('[name="csrfmiddlewaretoken"]').val()}, data: { name: 'alex', age: '73', }, success: function (res) { console.log(res); } }) });
結論 : 因爲每一次都這麼寫太麻煩了,可使用$.ajaxSetup()方法爲ajax請求統一設置。
3 全局設置:
注意: 使用$.ajaxSetup()方法爲ajax請求統一設置. 此時須要建一個js文件, 把下面的代碼粘進去就能夠.
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');
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中取值, 必須有cookie
有cookie的兩種方式:
1 使用{%csrf_token%};
2 from django.views.decorators.csrf import ensure_csrf_cookie
這個時候須要使用ensure_csrf_cookie()裝飾器強制設置Cookie。
$('#b2').click(function () { $.ajax({ url: '/csrf_test/', type: 'post', data: {}, success: function (res) { console.log(res); } }) });
4 三種方法的views的代碼:
from django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def csrf_test(request): if request.method == 'POST': print(request.POST) return HttpResponse('測試成功') return render(request, 'csrf_test.html')
5 利用ajax實現文件上傳
FormData對象: 能夠把全部表單元素的name與value組成一個queryString,提交到後臺。 在使用ajax提交時,使用FormData對象能夠減小拼接queryString的工做量
建立一個FormData空對象,而後使用append方法添加key/value:
formData.append('f1', $('#f1')[0].files[0]); # 因爲jquery獲取的對象是列表形式, 取出索引獲取一個dom對象, .files獲取文件列表, 取索引獲取該文件
文件上傳操做的代碼:
<body> {% csrf_token %} <input type="file" id="f1"> <button type="button" id="b1">上傳</button> <script src="/static/jquery-3.3.1.min.js"></script> <script> $('#b1').click(function () { var formData = new FormData(); formData.append('csrfmiddlewaretoken',$('[name="csrfmiddlewaretoken"]').val()); {#FormData添加文件類型數據#} formData.append('f1', $('#f1')[0].files[0]); $.ajax({ url:'/upload/', type:'post', data:formData, processData:false, contentType:false, success:function (ret) { console.log(ret) } }) }) </script>
views的內容:
def upload(request): if request.method == 'POST': print(request.FILES) fileobj = request.FILES.get('f1') with open(fileobj.name, mode='wb') as f: fileobj有name屬性. # chunks一點一點的讀 for i in fileobj.chunks(): f.write(i) return HttpResponse('ok') return render(request, 'upload.html')
6 註冊: 涉及到的內容, jquery綁定事件, ajax中沒有$(this)方法
html中的內容:
<body> <input type="text" id="t1" name="user"><span id="s1" style="color:red;"></span> {#<button id="b1">註冊</button>#} <script src="/static/jquery-3.3.1.min.js"></script> <script> $('#t1').blur(function () { {#console.log($(this));#} _this = $(this); {#因爲ajax中沒有$(this)這個方法,因此設置了一個全局變量#} $.ajax({ url:'/reg/', type:'post', data:{ user:$('#t1').val() }, success:function (res) { console.log(res); {#$('#s1').text(res)#} _this.next().text(res) } }) }).focus(function () { _this.next().text('') }) </script>
views中的代碼:
def reg(request): if request.method == 'POST': print(request.POST) user = request.POST.get('user') # 從數據庫中找到對象 obj = models.User.objects.filter(user=user).first() if obj: return HttpResponse('該用戶名已存在') else: return HttpResponse('該用戶名可使用') return render(request, 'reg.html')
7 登陸: 涉及到的內容 location.href = ''
html中的代碼:
<body> <input type="text" name="user" id="t1"> <input type="password" name="pwd" id="p1"> <button id="b1">登陸</button> <script src="/static/jquery-3.3.1.min.js"></script> <script> $('#b1').click(function () { $.ajax({ url:'/login/', type:'post', data: { user: $('#t1').val(), pwd: $('#p1').val() }, success: function (res) { console.log(res); if(res.status == '0'){ location.href = res.url } else{ alert(res.msg)}} }) }) </script> </body>
views中的代碼:
# 登陸 from django.http import JsonResponse def login(request): # 從ajax中的post方法中提交的數據中取出user和pwd if request.method == 'POST': ret = {'status': '0', 'msg': ''} user = request.POST.get('user') pwd = request.POST.get('pwd') # 數據庫中找到對應的對象: obj = models.User.objects.filter(user=user, pwd=pwd) if obj: ret['url'] = '/upload/' return JsonResponse(ret) # 若是該對象存在, 返回登陸成功 else: ret['status'] = '1' ret['msg'] = '用戶名或者是密碼錯誤' return JsonResponse(ret) # 若是不存在, 返回用戶名或者是密碼錯誤. return render(request, 'login.html')