Cookie與Session

Cookie

介紹

由於HTTP協議是無狀態的,所以每次請求都是獨立的,它的執行情況和結果與前面的請求和之後的請求都無直接關係,它不會受前面的請求響應情況直接影響,也不會直接影響後面的請求響應情況。

對服務器來說,每次的請求都是全新的。

狀態可以理解爲客戶端和服務器在某次會話中產生的數據,那無狀態的就以爲這些數據不會被保留。會話中產生的數據又是我們需要保存的,也就是說要“保持狀態”。因此Cookie就是在這樣一個場景下誕生。

概念

Cookie是一個非常具體的東西,指的就是瀏覽器裏面能永久存儲的一種數據,僅僅是瀏覽器實現的一種數據存儲功能。

cookie由服務器生成,發送給瀏覽器,瀏覽器把cookie以鍵值對的形式保存到某個目錄下的文本文件內

下次訪問服務器時瀏覽器會自動攜帶這些鍵值對,以便服務器提取有用信息。

補充: 

由於cookie是存在客戶端上的,所以瀏覽器加入了一些限制確保cookie不會被惡意使用,同時不會佔據太多磁盤空間,所以每個域的cookie數量是有限的。

原理

cookie的工作原理是:由服務器產生內容,瀏覽器收到請求後保存在本地;當瀏覽器再次訪問時,瀏覽器會自動帶上Cookie,這樣服務器就能通過Cookie的內容來判斷這個是“誰”了。

查看Cookie

我們使用Chrome瀏覽器,打開開發者工具。

Django中操作Cookie

設置Cookie

前提:

django返回給客戶端瀏覽器的都必須是HttpResponse對象

return HttpResponse()
return render()
return redirect()

設置:

obj = HttpResponse(...)
obj = render(request, ...)
​
obj.set_cookie(key,value,...)
obj.set_signed_cookie(key,value,salt='加密鹽', max_age=None, ...)

參數:

  • key, 鍵
  • value='', 值
  • max_age=None, 超時時間
  • expires=None, 超時時間(IE requires expires, so set it if hasn't been already.)
  • path='/', Cookie生效的路徑,/ 表示根路徑,特殊的:根路徑的cookie可以被任何url的頁面訪問
  • domain=None, Cookie生效的域名
  • secure=False, https傳輸
  • httponly=False 只能http協議傳輸,無法被JavaScript獲取(不是絕對,底層抓包可以獲取到也可以被覆蓋)

案例:

# 僞代碼
def lg(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'xionger' and password == '123':
            # 登錄成功跳到主頁
            obj = redirect('/home/')
            # 設置cookie值
            obj.set_cookie('name','xionger')  # 瀏覽器上會保存鍵值對name:xionger
            return obj
    return render(request,'lg.html')

獲取Cookie

request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)

參數:

  • default: 默認值
  • salt: 加密鹽
  • max_age: 後臺控制過期時間

案例:

# 僞代碼
def home(request):
    # 先校驗客戶端cookie中有沒有寫入的鍵值對
    if request.COOKIES.get('name'):
        return render(request, 'home.html')
    return HttpResponse('主頁只能登錄才能看')

刪除Cookie

obj.delete_cookie('key')

案例:

def logout(request):
    obj = redirect('/lg/')
    obj.delete_cookie('name')  # 刪除瀏覽器上的cookie鍵值對
    # 從定向到lg頁面
    return obj

Cookie版登陸

def lg(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'xionger' and password == '123':
            # 先獲取url中get請求攜帶的參數
            target_url = request.GET.get('next')
            # 判斷用戶是直接訪問登錄頁面還是從其他頁面跳過來的
            if target_url:
                obj = redirect(target_url)
            else:
                # # 如果用戶直接訪問的登陸頁面 那麼登陸完成之後 直接跳到網站的首頁
                obj = redirect('/home/')
            # 設置cookie值
            obj.set_cookie('name','xionger')  # 瀏覽器上會保存鍵值對name:xionger
            return obj
    return render(request,'lg.html')

Session

介紹

Cookie雖然在一定程度上解決了“保持狀態”的需求,但是由於Cookie本身最大支持4096字節,以及Cookie本身保存在客戶端,可能被攔截或竊取,因此就需要有一種新的東西,它能支持更多的字節,並且他保存在服務器,有較高的安全性。這就是Session。

問題來了,基於HTTP協議的無狀態特徵,服務器根本就不知道訪問者是“誰”。那麼上述的Cookie就起到橋接的作用。

我們可以給每個客戶端的Cookie分配一個唯一的id,這樣用戶在訪問時,通過Cookie,服務器就知道來的人是“誰”。然後我們再根據不同的Cookie的id,在服務器上保存一段時間的私密資料,如“賬號密碼”等等。

  • session是保存在服務端的數據(本質是鍵值對)
  • session的應用:依賴於cookie
  • session的作用:保持會話(web網站)
  • session的好處:敏感信息不會直接給客戶端,客戶端拿到的是session值(隨機字符串)

補充: Cookie和Session其實是共通性的東西,不限於語言和框架。

Django中操作Session

設置Session

request.session['key'] = 'value'

發生了三件事:

  • 1.django 內部自動生成一個隨機字符串
  • 2.將隨機字符串和你要保存的數據 寫入django_session表中(現在內存中生成一個緩存記錄 等到經過中間件的時候纔會執行)
  • 3.將產生的隨機字符串發送給瀏覽器寫入cookie

案例:

def set_session(request):
    request.session['name'] = 'xionger'
    request.session.set_ecpiry(30)
    return HttpResponse('設置session')
ps:設置的{name:xionger} 存放放到 django_session表中的session_data中

session值(隨機字符串):{name:'xionger',password:123,...}

ps:瀏覽器會設置一個鍵爲sessionid來存放session值(即隨機字符串) 如:  sessionid: k7z2t28sz15ms1ph...

獲取Session

request.session.get('key')  
# 有返回值,若對應的key沒有值,則返回None,設置的時候key是什麼,取的時候key就是什麼

發生了三件事:

  • 1.django內部會自動從請求信息中獲取到隨機字符串
  • 2.拿着隨機字符串去django_session表中比對
  • 3.一旦對應上了就將對應的數據解析出來放到request.session中

設置Session與獲取Session案例:

# 設置Session
def login(request):
    if request.method == 'POST':
        name = request.POST.get('username')
        pwd = request.POST.get('password')
        if name == 'xionger' and pwd == 123:
            # 1. 生成隨機的字符串
            # 2. 通過cookie發送給客戶端
            # 3. 服務端保存{隨機字符串:{name:xionger,...}}
            request.session['name'] = 'xionger'
            return redirect('/index/')
    return render(request,'login.html')

# 獲取Session
def index(request):
    # 1. 獲取客戶端cookie中的隨機字符串
    # 2. 取session中查看有沒有隨機字符串
    # 3. 取session對應的key的value中查看是否有name
    v = request.session.get('name')
    if v:
        return HttpResponse('登錄成功:%s'%v)  # >>> 登錄成功xionger
    else:
        return HttpResponse('請先登錄')

刪除Session

request.session.delete()
# 刪除當前會話的所有Session數據 (session_data中的鍵值對)
request.session.flush()
# 刪除當前的會話數據並刪除會話的Cookie。這用於確保前面的會話數據不可以再次被用戶的瀏覽器訪問
# 例如,django.contrib.auth.logout() 函數中就會調用它。

設置會話Session和Cookie的超時時間

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

注意:django默認的session存活時間是兩週(14天)

Session流程解析

補充:

執行了數據庫遷移命令就會生成django_session表,若報下面的錯只需要執行數據庫遷移命令即可

django_session表的其他用途

你在後期可以將一些數據保存到session表中,保存的數據 可以在後端任意位置獲取到
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章