Django之CSRF、token驗證、csrf裝飾器、auth模塊方法大全


什么是csrf?

CSRF即跨站請求攻擊。簡單的說,是攻擊者通過一些技術手段欺騙用戶的瀏覽器去訪問一個自己以前認證過的站點並運行一些操作(如發郵件,發消息,甚至財產操作(如轉賬和購買商品))。因為瀏覽器之前認證過,所以被訪問的站點會絕點是這是真正的用戶操作而去運行。

這就利用了web中用戶身份認證驗證的一個漏洞:簡單的身份驗證僅僅能保證請求發自某個用戶的瀏覽器,卻不能保證請求本身是用戶自願發出的。

​ 其實可以這么理解CSRF攻擊:攻擊者盜用了你的身份,以你的名義發送惡意請求。CSRF能夠做的事情包含:以你的名義發送郵件;發消息;盜取你的賬號;甚至於購買商品、虛擬貨幣轉賬......造成的問題包含個人隱私泄露以及財產安全。

大白話總結:自己准備一個擁有默認值(你的銀行卡號)的input框,隱藏起來。用戶輸入轉賬的input框,沒有name屬性。用戶發送轉賬請求的時候,后端拿到的是你已經准備好的銀行卡號,而不是用戶輸入的。

跨站請求偽造csrf
	釣魚網站
		本質搭建一個跟正常網站一模一樣的頁面
		用戶在該頁面上完成轉賬功能
		
		轉賬的請求確實是朝着正常網站的服務端提交
		唯一不同的在於收款賬戶人不同
		
		給用戶書寫form表單 對方賬戶的input沒有name屬性
		你自己悄悄提前寫好了一個具有默認的並且是隱藏的具有name屬性的input
	模擬釣魚網站

csrf原理

從上圖能夠看出,要完畢一次CSRF攻擊,受害者必須依次完畢兩個步驟:

​ 登錄受信任站點A,並在本地生成Cookie。

​ 在不登出A的情況下,訪問危急站點B。

如何預防CSRF?

1、提交驗證碼

​ 在表單中添加一個隨機的數字或字母驗證碼。通過強制用戶和應用進行交互。來有效地遏制CSRF攻擊。

2、Referer Check

​ 檢查假設是非正常頁面過來的請求,則極有可能是CSRF攻擊。

3、token驗證

(1)在 HTTP 請求中以參數的形式添加一個隨機產生的 token,並在服務器端建立一個攔截器來驗證這個 token,假設請求中沒有 token 或者 token 內容不對,則覺得可能是 CSRF 攻擊而拒絕該請求。

(2)token必須足夠隨機

(3)敏感的操作應該使用POST,而不是GET。比如表單提交。

4、在HTTP頭中自己定義屬性並驗證

​ 這樣的方法也是使用 token 並進行驗證。這里並非把 token 以參數的形式置於 HTTP 請求之中,而是把它放到 HTTP 頭中自己 定義的屬性里。通過 XMLHttpRequest 這個類,能夠一次性給全部該類請求加上 csrftoken 這個 HTTP 頭屬性。並把 token 值放入當中。這樣攻克了上種方法在請求中添加 token 的不便。同一時候,通過 XMLHttpRequest 請求的地址不會被記錄到瀏覽器的地址欄,也不用操心 token 會透過 Referer 泄露到其它站點中去。

form表單中如何通過csrf校驗?

你只需要在你的form表單內寫一個  {% csrf_token %}


<form action="" method="post">
    {% csrf_token %}
    old_password:<input type="text" name="old_password">
    new_password:<input type="text" name="new_password">
    <input type="submit">

</form>

AJAX如何通過csrf校驗?

第一種方式:自己手動獲取

$('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            // 第一種方式 自己手動獲取
data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},
            success:function (data) {
                alert(data)
            }
        })
    })

第二種方式:利用模板語法

$('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
           // 第二種方式 利用模板語法
            data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},
            success:function (data) {
                alert(data)
            }
        })
    })

第三種方式:通用方式 引入外部js文件 官網提供的方式

$('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
		   <script src="{% static 'myset.js' %}"></script>
            success:function (data) {
                alert(data)
            }
        })
    })

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);
    }
  }
});

CSRF相關裝飾器

1.登錄認證裝飾器

使用的時候需要導入:
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator

@csrf_exempt  # 不校驗csrf
@csrf_protect # 校驗

使用方法

1.在指定函數頭上裝

@method_decorator(csrf_protect)  # 第一種方式
def post(self,request):
	return HttpResponse('post')

2.在類名頭上指名道姓給某個方法裝

@method_decorator(csrf_protect,name='post') 
class MyHome(View): 
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request,*args,**kwargs)
    def post(self,request):
        return HttpResponse('post')
    def get(self,request):
        return HttpResponse('get')

3.類中所有方法都裝

class MyHome(View): 
    @method_decorator(csrf_protect)  # 第三種 類中所有的方法都裝
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request,*args,**kwargs)
    def post(self,request):
        return HttpResponse('post')
    def get(self,request):
        return HttpResponse('get')

2.校驗用戶是否登錄裝飾器

from django.contrib.auth.decorators import login_required

使用方式:

@login_required(login_url='/index/') 可以傳參數,重定向到頁面。這是是局部。

@login_required(login_url='/index/')
def yyy(request):
    return HttpResponse('yyy頁面')

全局修改參數方式:修改之后,影響全局。局部也可以修改。局部修改就用局部的

在settings.py中添加:LOGIN_URL = '/login/'

Django用戶相關自帶功能模塊 auth

auth方法大全

from django.contrib import auth

1.創建用戶
    User.objects.create()  				 # 創建普通用戶,密碼是明文。不推薦
    User.objects.createuser()  			 # 創建普通用戶,基本都用它 
    User.objects.createsuperuser()  	 # 創建超級用戶,郵箱要給數據
    
2.校驗用戶名和密碼是否正確  
    auth.authenticate(username=username,password=password)  # 用戶名和密碼兩個一個都不能少
							# 該方法返回值:當用戶名和密碼正確的時候:返回的用戶對象 
        											 #不正確返回None
3.保存登錄狀態
	auth.login(request,user_obj)  # 這一句執行之后 request.user就能獲取當前登錄的用戶對象
    
4.如何判斷當前用戶是否登錄 以及如何獲取當前登錄用戶對象
	request.user.is_authenticated()  # 判斷是否登錄  BOOL值
    request.user  # 登錄用戶對象
    
5.校驗用戶是否登錄
    from django.contrib.auth.decorators import login_required
    # 局部配置
    @login_required(login_url='/login/')    # 沒有登錄跳轉的頁面
    def xxx(request):
        return HttpResponse('xxx頁面')	  # 登錄之后的
			
    # 全局配置
    配置文件中寫以下代碼
    LOGIN_URL = '/login/'
    @login_required
    def xxx(request):
    	return HttpResponse('xxx頁面')
		# 如果兩個都設置了 那么優先執行局部配置
		
6.修改密碼
    request.user.check_password(old_password)  # 校驗原密碼是否正確
    request.user.set_password(new_password)
    request.user.save()                        # 一定要保存 
		
7.注銷功能
	auth.logout(request)  	# 刪除了對應的session值

如何擴展auth_user表?

# 1 利用一對一表關系()
	
	
# 2 利用類的繼承
    # 1 類的繼承
    from django.contrib.auth.models import User,AbstractUser
    # Create your models here.
    class Userinfo(AbstractUser):
    phone = models.BigIntegerField()
    avatar = models.FileField()
    # 擴展的字段 盡量不要與原先表中的字段沖突

    # 2 配置文件
    AUTH_USER_MODEL = '應用名.表名'
    """
    django就會將userinfo表來替換auth_user表
    並且之前auth模塊所有的功能不變 參照的也是userinfo表
    """


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM