cookie和session django中間件

[TOC]html

1、cookie和session

1. 爲何要有cookie和session

  • 目的是爲了保存客戶端的用戶狀態
  • http協議是無狀態的

2、cookie

1. 什麼是cookie

  • 簡單來講,cookie就是保存在客戶端瀏覽器上的鍵值對
  • 瀏覽器中保存的cookie即這些鍵值對是由服務端設置的,再保存到客戶端瀏覽器上。瀏覽器有權禁止cookie的寫入(就是瀏覽器不保存cookie)

2. django中關於cookie的使用

(1)後端設置cookie

  • 以前在django後端的視圖層中,視圖函數最後返回的都是HttpResponse對象,但如今,咱們操做cookie,則須要使用HttpResponse對象來設置cookie
  • 經過HttpResponse對象.set_cookie('key','value')語句來設置cookie
  • 實例:在登錄成功時設置cookie
def login(request):
	if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'jason' and password == '123':
            # 登陸成功
            old_path = request.GET.get('next')  # 登錄成功後要跳轉的url(使用登錄認證裝飾器在登錄的url後面攜帶get請求參數——》 ?next=url)
            if old_path:  # 防止用戶直接訪問的login頁面
                obj = redirect(old_path)
            else:
                obj = redirect('/home/')  # 默認跳轉到首頁 當用戶沒有想要訪問的網址
            obj.set_cookie('whoami','jason')  # 告訴瀏覽器保存一個鍵值對
            return obj
    return render(request,'login.html')

(2)後端獲取cookie

  • 經過request.COOKIES.get(key)語句來獲取cookie前端

  • 實例:設計登錄認證裝飾器python

from functools import wraps  
def login_auth(func):
    @wraps(func)  # wraps做用是 修復被裝飾的函數
    def inner(request,*args,**kwargs):
        # 判斷當前用戶是否登陸
        # print('request.path_info:',request.path_info)  # 只獲取url
        # print('request.get_full_path():',request.get_full_path())  # url+get請求的參數
        if request.COOKIES.get('whoami'):
            res = func(request,*args,**kwargs)
            return res
        else:
            target_path = request.path_info
            return redirect('/login/?next=%s'%target_path)
    return inner

(3)設置cookie的超時時間

  • cookie的超時時間是指該cookie在瀏覽器上可以保存的時間,從該cookie在瀏覽器上出現開始計算。
  • 設置語法:
    • HttpResponse對象.set_cookie('key','value',max_age=n)
    • HttpResponse對象.set_cookie('key','value',expires=n)
      • 最後的一個參數都是設置超時時間,而且都是以秒爲單位
      • 區別:若是你要給IE瀏覽器設置cookie的超時時間,你只能用expires

(4)刪除cookie

  • 刪除cookie會讓瀏覽器立馬清楚其保存的響應的鍵值對程序員

  • 刪除語法:HttpResponse對象.delete_cookie(key)算法

  • 實例:登出/註銷功能數據庫

@login_auth
def logout(request):
    obj = redirect('/home/')
    obj.delete_cookie('whoami')
    return obj

3、session

1. 什麼是session

  • session是保存在服務端上的鍵值對,在客戶端的cookie中也保留一個session的鍵。
  • session的工做機制須要依賴於cookie
    • 客戶端瀏覽器上的cookies的其中之一的一個鍵值對是sessionid:session的鍵生產的隨機字符串
  • session的鍵實際上是世界上惟一的一個字符串,值是咱們自定義的一些數據。雖然在咱們設置session時,本身給出了一個任意的字符串當作session的key,可是django後端會自動將該key轉變成一個世界上惟一的字符串,而且還將這個key對應的值進行加密,最後默認保存在數據庫django_session表中(固然也能夠經過修改一些設置,讓session保存在其餘本地文本文件中或內存中)。

2. django中關於session的使用

(1) 設置session

  • 設置session語法:request.session[key] = valuedjango

    • 第一次設置的時候可能會報錯,是由於你沒有執行數據庫遷移命令生成django須要用到的一些默認表(django_session)
  • django默認的session失效時間是14天後端

  • 當執行request.session[key] = value這句語句時發生的事:瀏覽器

    1. djang內部自動幫你調用算法生成一個隨機的字符串做爲session的key,並把該key對應的值進行加密
    2. 在django_session表中添加數據(數據保存方式: 隨機字符串 加密後的數據 失效時間)
    3. 將產生的隨機字符串返回給客戶端瀏覽器 讓瀏覽器保存
  • 注意:一個項目中,其數據庫的django_session表中,不管有多少個session,經過同一種瀏覽器設置的session只會保存在一行記錄中。不一樣瀏覽器設置的session纔會保存在不一樣的行中。cookie

(2)獲取session

  • 語法:request.session.get(key)key是咱們以前設置session時,指定的key,不是生成的那個隨機字符串。
  • 當執行request.session.get(key)時發生的事:
    1. django內部會自動去請求頭裏面獲取cookie
    2. 拿着sessionid所對應的隨機字符串去django_sessoion表中一一比對
    3. 若是比對上了,會將隨機字符串對應的數據獲取出來,自動放入request.session中供程序員調用,若是沒有就是一個空字典

(3)設置失效時間

  • 語法:request.session.set_expiry(value)

    • 若是value是個整數,session會在些秒數後失效。
    • 若是value是個datatime或timedelta,session就會在這個時間後失效。
    • 若是value是0,用戶關閉瀏覽器session就會失效。
    • 若是value是None,session會依賴全局session失效策略。
  • 失效時間是指到了這個時間,保存在服務端的django_session表中的這個session數據就沒用了。以後會被刪除。且客戶端瀏覽器上的sessionid的這個cookie也會失效。

(4)刪除session

  • 語法:
    • request.session.delete()
      • 客戶端和服務端的關於session的會所有刪除,數據庫中只會根據瀏覽器的不一樣刪對應的數據
    • request.session.flush()
      • 該方法只會刪除瀏覽器上的sessionid的那個cookie,服務端的只會到了失效時間後再刪除(建議使用這個)

4、token

5、django中間件

  • django中間件的做用很是強大,請求數據到後端要通過中間件,視圖函數響應的數據(return返回的數據)也要通過中間件。
  • 數據在經過中間件時,中間件都有各自獨立的功能,在特定狀況下對數據作相應的處理。
  • django默認有七個中間件
  • django支持自定義中間件
  • django中間件的做用
    1. 全局的用戶登陸校驗
    2. 全局的用戶訪問頻率校驗
    3. 全局的用戶權限校驗()

1. 數據經過django中間件的流程

(1)正常流程

  • 請求數據到django後端的django中間件後,按照從上到下的順序依次經過settings文件中MIDDLEWARE中書寫的各個中間件——》
  • 數據到視圖層,視圖層再返回響應數據——》
  • 響應數據再按照從下到上的順序依次經過settings文件中MIDDLEWARE中書寫的各個中間件。

(2)特殊狀況

  • 當中間件中的process_request 方法返回了一個HttpResponse對象,那麼請求會馬上中止日後面走(下面的中間件和以後的視圖函數都不走),當即原路返回

2. django中間件中經常使用的方法

  • django各個中間件中通常都含有一個process_request process_response 方法
  • 這些方法都含有request形參,放在self以後
  • 若是形參中含有response 那麼必需要返回,若返回其餘,則響應數據就會變成其餘。

(1)process_request

  • 請求來的時候會按照settings配置文件中從上往下的順序,依次執行每個中間件內部定義的process_request方法

  • 當請求數據走到中間件時,會執行該方法。若該中間件沒有該方法,則會跳過該中間件繼續走下一個中間件

  • 該方法一旦返回了HttpResponse對象,那麼請求會馬上中止日後走,當即原路返回(當process_request方法直接返回HttpResponse對象以後,會直接從當前中間件裏面的process_respone往回走)

  • 方法參數:

    def process_request(self,request):

(2)process_response

  • 視圖函數返回的響應數據走的時候,會按照settings配置文件中從下往上的順序,依次執行每個中間件內部定義的process_response方法

  • 該方法必須有兩個形參request,response,而且必須返回response形參,不返回直接報錯

  • 該方法返回什麼(HttpResponsed對象) 前端就能得到什麼,即該方法返回的數據會覆蓋掉以前視圖函數返回的響應數據。而且若該中間件上面的中間件的process_response方法也返回了HttpResponsed對象,則會再把該中間件的返回數據再覆蓋掉。

  • 方法參數:

    def process_response(self,request,response):

(3)process_view

  • 路由匹配成功以後執行視圖函數以前觸發該方法

  • 若是該方法返回了HttpResponse對象 那麼會從下往上一次通過每個中間件裏面的process_response方法

  • 方法參數:

    def process_view(self,request,view_name,*args,**kwargs):
    
    # view_name 是要執行的視圖函數的內存地址

(4)process_template_response

  • 當你返回的對象中含有render屬性指向的是一個render方法的時候纔會觸發,從下往上的順序

  • 方法參數:

    def process_template_response(self, request, response):
  • 實例

# 讓後端視圖函數中返回的對象含有render屬性的方式
def mdzz(request):
	print('我是視圖函數mdzz')  
	def render():
		return HttpResponse('你好呀 我是奇葩')
	obj = HttpResponse('我很好 好的像個傻逼同樣')
	obj.render = render
	return obj

# 響應數據變成了: 我是視圖函數mdzz

(5)process_exception

  • 當視圖函數中出現錯誤,會自動觸發,順序是從下往上

  • 方法參數:

    def process_exception(self, request, exception):

3. 自定義中間件

  • 注意:django暴露給用戶五個能夠自定義的方法(就是上面提到的5個django中間件經常使用的方法)來自定義中間件

(1)自定義中間件的步驟

  1. 在應用文件下(如:app01)新建一個任意名字的文件夾(如:mymddleware)

  2. 在mymddleware文件下新建一個任意名字的py文件(如:mymdd.py)

  3. 導入方法

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse,render,redirect
  4. 在mymdd文件中自定義類,一個類就是一箇中間件。類內部寫上面提到的5個django中間件中經常使用的方法

  5. 在settings文件的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',
        'app01.mymiddleware.mymdd.MyMdd1',  # 添加自定義中間件
        'app01.mymiddleware.mymdd.MyMdd2',  # 添加自定義中間件
    ]

(2)自定義django中間件實例

class MyMdd1(MiddlewareMixin):
    def process_request(self,request):
        print('我是第一個中間件裏面的process_request方法')
        # return HttpResponse("我是中間件一里面的")

    def process_response(self,request,response):
        """
        :param request:
        :param response: 就是後端返回給前端的數據
        :return:
        """
        print('我是第一個中間件裏面的process_response方法')
        return response
        # return HttpResponse("我是中間件一里面的")

    def process_view(self,request,view_name,*args,**kwargs):
        print(view_name)
        print(args)
        print(kwargs)
        print('我是第一個中間件裏面的process_view方法')
        # return HttpResponse("我是中間件一里面的process_view")

    def process_exception(self,request,exception):
        print('我是第一個中間件裏面的process_exception')
        print(exception)

    def process_template_response(self, request, response):
        print('我是第一個中間件裏面的奇葩方法')
        return response
    
class MyMdd2(MiddlewareMixin):
    def process_request(self,request):
        print('我是第二個中間件裏面的process_request方法')
        # return HttpResponse('我是中間件二里面的')

    def process_response(self,request,response):
        """
        :param request:
        :param response: 就是後端返回給前端的數據
        :return:
        """
        print('我是第二個中間件裏面的process_response方法')
        return response

        # return HttpResponse("我是中間件二里面的")
    def process_view(self,request,view_name,*args,**kwargs):
        print(view_name)
        print(args)
        print(kwargs)
        print('我是第二個中間件裏面的process_view方法')
        # return HttpResponse("我是中間件二里面的process_view")

    def process_exception(self, request, exception):
        print('我是第二個中間件裏面的process_exception')
        print(exception)

    def process_template_response(self, request, response):
        print('我是第二個中間件裏面的奇葩方法')
        return response
相關文章
相關標籤/搜索