django-csrf跨站請求偽造
一、什么是跨站請求偽造
跨站請求偽造,英文簡稱:csrf,英文全稱:cross-site request forgery
舉個栗子:釣魚網站
有一個和某銀行一摸一樣的虛假網站,用戶在該頁面完成轉賬功能,轉賬的請求是朝著銀行的真實網站的服務端提交,這兩個網站提交資料的唯一不同在于收款賬戶人不同,在虛假網站書寫收款人的form表單,此頁面的input輸入框沒有name屬性,虛假網站開發人員提前寫好一個具有默認的并且是隱藏的具有name屬性的input,所以向銀行真實服務端提交資料的時候,默認就是將你的金額轉給了默認寫好的賬戶,這種虛假網站就叫做釣魚網站,這種方式叫做跨站請求偽造,
那么如何開啟csrf校驗,防止此類事情出現呢?
二、django如何開啟csrf校驗
csrf是django的默認中間件,默認是開啟的,對前端請求進行校驗;將其注釋即關閉校驗,

但是在開啟情況下,前端向后臺提交資料會被阻攔報出 403 forbidden 錯誤,那么如何通過這種校驗呢?
PS:關閉csrf中間件即可通過校驗,但是出于資料安全考慮,不建議此類操作,可做簡單測驗使用,不推薦使用于生產環境,下文不對此方法進行敘述,
三、如何正確通過csrf校驗
1、前端的form表單如何通過csrf校驗
在form表單內書寫一個{% csrf_token %}即可,例:

這樣的話,后端會回傳給前端一串隨機字串,前端向后端再次發送資料時,后端的csrf中間件會對這一串字串進行校驗,校驗成功正確即回傳資料,校驗不成功即 403 forbidden 報錯,

2、ajax如何通過csrf校驗
第一種:手動獲取
$.ajax({ url: '', type: 'post', // 第一種方式:手動獲取 data:{'username':'tom', 'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()} success:function (data) { alert(data) } })
第二種:利用模板語法
$.ajax({ url: '', type: 'post', // 第二種方式:使用模板語法 data:{'username':'tom', 'csrfmiddlewaretoken':'{{ csrf_token }}'} success:function (data) { alert(data) } })
第三種:通用方式,引入外部js檔案
① cv大法,創建myset.js
function getCookie(name) { var cookieValue = https://www.cnblogs.com/jsxxd/archive/2020/12/15/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); } } });自定義myset.js檔案
② 在html中引入檔案
// 加載靜態檔案 {% load static %} // 引入自定義myset.js檔案 <script src="https://www.cnblogs.com/jsxxd/archive/2020/12/15/{% static'myset.js' %}"></script>
③ ajax按照語法正常寫即可
$.ajax({ url: '', type: 'post', // 第三種方式:通用方式,引入外部js檔案 data:{'username':'tom'} success:function (data) { alert(data) } })
四、csrf相關裝飾器
1、當網站整體都使用csrf校驗的時候,我想讓某幾個視圖函式不使用csrf校驗(組態檔中中間件配置csrf沒有被注釋,默認全部校驗)

(1)FBV:基于函式的視圖
from django.views.decorators.csrf import csrf_exempt, csrf_protect @csrf_exempt # 整體都校驗,該視圖函式不校驗csrf def login(request): return render(request, 'login.html')
(2)CBV:基于類的視圖
csrf_exempt的兩種方式:
# csrf_exempt的兩種方式: from django.views import View from django.views.decorators.csrf import csrf_exempt, csrf_protect from django.utils.decorators import method_decorator # @method_decorator(csrf_protect, name='dispatch') # 第二種方式:一定要指定dispatch方法,所以第二種方法==第一種方法 class MyHome(View): @method_decorator(csrf_exempt) # 第一種方式:給類中所有的方法都加上裝飾器 def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) def get(self, request): return render(request, 'get_demo.html') def post(self, request): return HttpResponse('請求完成')
2、當網站整體都不使用csrf校驗的時候,我想讓某幾個視圖函式使用csrf校驗(組態檔中中間件配置csrf被注釋,默認全部不校驗)

(1)FBV:基于函式的視圖
from django.views.decorators.csrf import csrf_exempt, csrf_protect @csrf_protect # 整體都不校驗,該視圖函式校驗csrf def login(request): return render(request, 'login.html')
(2)CBV:基于類的視圖
csrf_protect的三種方式:
# csrf_protect的三種方式: from django.views import View from django.views.decorators.csrf import csrf_exempt, csrf_protect from django.utils.decorators import method_decorator @method_decorator(csrf_protect, name='post') # 第二種方式:指名道姓的給某個方法裝飾 class MyHome(View): # @method_decorator(csrf_protect) # 第三種方式:給類中所有的方法都加上裝飾器 def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) def get(self, request): return render(request, 'get_demo.html') # @method_decorator(csrf_protect) # 第一種方式:直接在方法上面裝飾 def post(self, request):
3、總結
① 給CBV加裝飾器,推薦使用method_decorator模塊
② 自定義的裝飾器和csrf_protect的用法一致
③ 唯獨scrf_exempt是一個特例,只能給dispatch方法裝飾
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/235274.html
標籤:其他
上一篇:你還在用分頁?試試 MyBatis 流式查詢,這個你知道嗎?
下一篇:Java基礎語法吐血整理
