1. 程式人生 > 其它 >Django---cookie和session操作,CBV新增裝飾器,中介軟體,csrf請求和解決策略

Django---cookie和session操作,CBV新增裝飾器,中介軟體,csrf請求和解決策略

目錄

django操作cookie補充


加密鹽

set_signed_cookie(key,value,salt='加密鹽')
# 會在value後面產生一個字串eg:1ntTFz:bFkwr34ztzsHQLU1qYp

後臺控制過期時間

set_signed_cookie(key,value,max_age=超時時間:預設是秒數)
# expires:專門針對IE瀏覽器設定超時時間

刪除Cookie

# HttpResponse物件.delete_cookie(key) 
def logout(request):
    rep = redirect("/login/")
    rep.delete_cookie("user")  # 刪除使用者瀏覽器上之前設定的usercookie值
    return rep

django操作session


設定

request.session['key'] = value  # 可以設定多組

獲取

request.session.get('key')  # 可以獲取多組

服務端儲存使用者相關狀態資訊,返回給客戶端隨機字串。針對儲存django需要一張表來處理,就是django資料庫遷移命令會產生一堆預設的表中的django_session表。裡面只有三個欄位(session_key,session_data,expire_date)。

設定session內部發生的事情:

  1. 產生一個隨機字串
  2. 表中儲存隨機字串與加密資料的對應關係
  3. 並將產生的隨機字串也給客戶端傳送一份並讓其儲存
  4. sessionid:隨機字串

獲取session內部發送的事情:

  1. 自動獲取客戶端請求中的隨機字串
  2. 自動去儲存session資料的表中比對
  3. 如果比對成功自動獲取並'解密處理'

ps:django預設的session失效時間是14天。

session補充

獲取產生的隨機字串

request.session.session_key

只刪客戶端

request.session.delete()

服務端和客戶端都刪

request.session.flush()

設定超時時間

request.session.set_expiry(value)
* 如果value是個整數,session會在些秒數後失效。
* 如果value是個datatime或timedelta,session就會在這個時間後失效。
* 如果value是0,使用者關閉瀏覽器session就會失效。
* 如果value是None,session會依賴全域性session失效策略。

針對session資料的儲存位置,有五種方案:

1. 資料庫Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(預設)

2. 快取Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
SESSION_CACHE_ALIAS = 'default'                            # 使用的快取別名(預設記憶體快取,也可以是memcache),此處別名依賴快取的設定

3. 檔案Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
SESSION_FILE_PATH = None                                    # 快取檔案路徑,如果為None,則使用tempfile模組獲取一個臨時地址tempfile.gettempdir() 

4. 快取+資料庫
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎

5. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎

CBV新增裝飾器


想要在CBV上新增裝飾器,我們則需要藉助於一個專門的裝飾器模組來實現。

from django.utils.decorators import method_decorator

方式1:直接在類中的某個方法上新增

class MyLoginView(views.View):
    @method_decorator(login_auth)
    def get(self, request):
        return HttpResponse("from CBV get view")

方式2:直接在類名上新增並指定

@method_decorator(login_auth, name='get')
class MyLoginView(views.View):
    def get(self, request):
        return HttpResponse("from CBV get view")

方式3:重寫dispatch方法並新增作用於類中所有的方法

class MyLoginView(views.View):
    @method_decorator(login_auth)
    def dispatch(self, request, *args, **kwargs):
        super().dispatch(request,*args,**kwargs)

django中介軟體


django請求生命週期流程圖

什麼是中介軟體?

官方的說法:中介軟體是一個用來處理Django的請求和響應的框架級別的鉤子。說的直白一點中介軟體是幫助我們在檢視函式執行之前和執行之後都可以做一些額外的操作,它本質上就是一個自定義類,類中定義了幾個方法,Django框架會在請求的特定的時間去執行這些方法。

我們一直都在使用中介軟體,只是沒有注意到而已,開啟Django專案的Settings.py檔案,看到下圖的MIDDLEWARE配置項。

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

django中介軟體的使用場景:只要是全域性相關的功能都可以在中介軟體中編寫。eg:使用者黑名單校驗、使用者訪問頻率校驗、網站全域性使用者身份校驗。

自定義中介軟體


jango不單有七個中介軟體並且每個都有很多功能和方法,除此之外django還支援自定義中介軟體並提供五個可以自定義的方法。

process_request(self,request)
process_view(self, request, view_func, view_args, view_kwargs)
process_template_response(self,request,response)
process_exception(self, request, exception)
process_response(self, request, response)

操作

  1. 建立一個任意名稱的資料夾
  2. 在該資料夾內建立一個任意名稱的py檔案
  3. 在該py檔案內編寫中介軟體類
  4. 配置檔案中註冊
# 步驟二建立的py檔案
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse,redirect,render

class MyMdd1(MiddlewareMixin):
    def process_request(self, request):
        print('自定義中介軟體:from MyMdd1 process_request')
        # return HttpResponse('from MyMdd1 process_request')

    def process_response(self, request, response):
        print('自定義中介軟體:from MyMdd1 process_response')
        return response  # response就是檢視函式返回給客戶端的資料
# settings
MIDDLEWARE = [
    # 註冊自定義中介軟體
    'app01.mymiddleware.mymdd.MyMdd1',
    'app01.mymiddleware.mymdd.MyMdd2',
]

必須要掌握的方法

  • process_request
def process_request(self, request):
        print('自定義中介軟體:from MyMdd1 process_request')
        return HttpResponse('from MyMdd1 process_request')
1.請求來的時候會從上往下依次執行配置檔案中註冊了的中介軟體裡面的process_request方法,如果沒有則直接跳過
2.如果該方法自己返回了HttpResponse物件,那麼請求不再繼續往後直接返回相應的資料
  • process_response
def process_response(self, request, response):
        print('自定義中介軟體:from MyMdd1 process_response')
        return response  # response就是檢視函式返回給客戶端的資料
1.響應走的時候會從下往上依次執行配置檔案中註冊了的中介軟體裡面的process_response方法,如果沒有則直接跳過
2.如果該方法自己返回了HttpResponse物件,那麼響應會替換成該HttpResponse物件資料,而不再是檢視函式想要返回給客戶端的資料

PS:如果process_request返回了HttpResponse物件,那麼會從當前位置從下往上執行每一個process_response。

需要了解的方法

  • process_view
    def process_view(self,request,view_func, view_args, view_kwargs):
        # print('view_func',view_func)  # 即將要執行的檢視函式名
        # print('view_args',view_args)  # 傳給檢視函式的位置引數
        # print('view_kwargs',view_kwargs)  # 傳給檢視函式的關鍵字引數
        print('自定義中介軟體:from MyMdd2 process_view')
路由匹配成功之後執行檢視函式之前從上往下執行配置檔案中註冊了的中介軟體裡面的process_view方法
  • process_template_response
    def process_template_response(self,request,response):
        print('自定義中介軟體:from MyMdd2 process_template_response')
        return response
檢視函式執行完畢之後返回的物件中含有render屬性對應一個render方法,則會從下往上執行配置檔案中註冊了的中介軟體裡面的process_template_response方法
  • process_exception
    def process_exception(self,request,exception):
        print(exception)
        print('自定義中介軟體:from MyMdd2 process_exception')
檢視函式執行過程中報錯並在返回響應的時候會從下往上執行配置檔案中註冊了的中介軟體裡面的process_exception

csrf跨站請求偽造和解決策略


前戲

釣魚網站:一個模仿正規網站的網址 誘騙使用者在該網站上做本應該在正規網站上做的操作,從而獲取到該使用者在正規網站上的資料甚至是財產。eg:假設我們需要登入網頁完成轉賬操作,我們不小心登入到了釣魚網站,填寫了賬戶,密碼,對方賬戶等資訊,點選轉賬之後我們賬戶的錢確實減少了,但是對方賬戶卻變成了一個你從來不認識的人。

原理:將收款人的賬號,提前寫成犯罪分子的然後隱藏,暴露給使用者一個沒有name屬性的標籤寫著玩。

<p>當前賬戶:<input type="text" name="current_user"></p>
<p>目標賬戶:<input type="text" ></p>  # 寫著玩,沒有功能
<p>目標賬戶:<input type="text" name="target_user" style="display: none" value="犯罪分子"></p>  # 真正轉賬物件,通過display: none隱藏了
<p>轉賬金額:<input type="text" name="money"></p>

解決策略


form表單

<form action="" method="post">
{% csrf_token %}
<p>當前賬戶:<input type="text" name="current_user"></p>
<p>目標賬戶:<input type="text" name="target_user"></p>
<p>轉賬金額:<input type="text" name="money"></p>
<input type="submit">
</form>

會自動產生一個input標籤,用於校驗。submit提交的時候會帶上這個生成的input裡的value值,然後會和之前後端返回的頁面裡的value進行比對,如果正確,這個提交請求就讓它過,如果不正確就步讓請求通過。

<input type="hidden" name="csrfmiddlewaretoken" value="iQOCyIe4ETIYSfVSji3SqJlt3XeEJs8pujSuiNG5aKHrKZbfzusiLQ5erZHnfpk8"> # value隨機

ajax請求

方式1:頁面任意位置先寫{% csrf_token %} 之後獲取資料

'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()

方式2:模板語法直接獲取

'csrfmiddlewaretoken':{{ csrf_token }}

通用解決方案:js指令碼自動處理(只能適用於ajax提交),建立一個js檔案,複製下面內容,然後在頁面上引入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);
    }
  }
});