目錄
一.Cookie與Session的發展史
1.Cookie的發展史
2.Session的發展史
3.Cookie和Session的關系
4.總結
二.Cookie與Session詳解
1.Cookie
2.Session
3.token
4.總結
三.Django操作Cookie
1.設置Cookie
2.獲取Cookie
3.設置超時時間
4.注銷Cookie
5.登錄功能實現
(1.0)簡單實現
(2.0)解決登錄問題
(3.0)迭代-登錄認證裝飾器
四.Django操作Session
1.設置Session
2.獲取Session
3.設置/獲取Session多個值
4.django_session表中的session數據
5.設置過期時間
6.清空session
(1)request.session.delete():
(2)request.session.flush():
7.保存
原理剖析
案例演示
(1.0)簡單的
(2.0)解決方法
(3.0)優化
一.Cookie與Session的發展史
Cookie和Session是用來在Web應用程序中跟蹤用戶會話數據的兩種常用技術
1.Cookie的發展史
- 1994年,網景通信公司推出了第一個瀏覽器Cookie技術。Cookie是存儲在用戶計算機上的小型文本文件,用于跟蹤用戶在網站上的活動。
- 初始版本的Cookie只能存儲很少的數據,并且沒有強制加密機制,容易被惡意用戶篡改或竊取。因此,隨著互聯網的快速發展,Cookie引起了一系列安全和隱私問題。
2.Session的發展史
- 由于Cookie存在的局限性,Web開發人員開始尋找更安全、可靠的替代方案。1997年,Sun Microsystems提出了基于服務器的會話管理方案,即Session。
- Session是在服務器端存儲用戶會話數據的一種技術。每當用戶訪問網站時,服務器會為其創建一個唯一的Session標識符(Session ID),并將會話數據存儲在服務器上。
- Session ID一般通過Cookie或URL參數傳遞給客戶端,用于識別用戶的會話狀態。
3.Cookie和Session的關系
- 在實際應用中,Cookie和Session通常結合使用。當用戶首次訪問網站時,服務器會為其分配一個唯一的Session ID,并將其存儲在Cookie中,發送給客戶端保存。
- 隨后,客戶端在每次請求中都會攜帶該Cookie,服務器通過解析Cookie中的Session ID,讀取對應的會話數據,實現用戶狀態的跟蹤和管理。
4.總結
Cookie和Session是Web應用程序中常用的用戶會話跟蹤技術
Cookie通過在客戶端存儲小型文本文件,并將會話標識符傳遞給服務器,實現會話狀態的保持
Session則是在服務器端存儲會話數據,通過Session ID實現對用戶會話的追蹤
他們的發展歷程與互聯網的發展緊密相關,為開發人員提供了更多的選擇以保障安全性和用戶體驗的提升
二.Cookie與Session詳解
以登錄功能為例:
? ? ? ? 如果不保存用戶登錄狀態也就意味著用戶每次訪問網站都需要重復的輸入用戶名和密碼
? ? ? ? 這對用戶來說體驗極差
解決方法:
? ? ? ? 當用戶第一次登錄成功之后將用戶的用戶名和密碼返回給瀏覽器,讓用戶瀏覽器保存在本地
? ? ? ? 之后訪問網站的時候瀏覽器自動將保存在本地的用戶名和密碼發送給服務端,服務端獲取之后自動驗證,但是具有極大的安全隱患
優化:
? ? ? ? 當用戶登錄成功之后,服務端產生一個隨機字符串(在服務端保存數據,用K:V鍵值對的形式),交由客戶端瀏覽器保存
? ? ? ? 之后訪問服務端時都帶著隨機字符串,服務端去數據庫中比對是否有匹配到的隨機字符串,從而獲得用戶信息
? ? ? ? 但是如果截取到當前隨機字符串,那么就可以冒充當前用戶,其實還是有極大的安全隱患
? ? ? ? 在web領域沒有絕對的安全和絕對的不安全
1.Cookie
- 服務器保存在客戶端瀏覽器上的信息都可以稱之為cookie
- 它的表現形式一般都是K:V鍵值對(可以有多個)
2.Session
- 保存在服務器上的信息都可以稱之為session
- 它的表現形式一般都是K:V鍵值對(可以有多個)
3.token
- session雖然數據是保存在服務端的,但是擋不住數據量大
- 解決辦法:服務端不再保存數據
- 登錄成功之后將一段信息加密處理(用自己獨特的加密方式進行加密)
- 將加密之后的結果拼接在信息后面,整體返回給瀏覽器保存
- 瀏覽器下次訪問的時候帶著該信息,服務端自動切取前面的一段信息再次使用自己的加密算法進行加密
- 然后用這段密文與攜帶過來的密文進行比對
4.總結
- cookie就是保存在客戶端瀏覽器上的信息
- session就算保存在服務端上的信息
- session是基于cookie工作的(其實大部分的保存用戶狀態的操作都需要使用cookie)
三.Django操作Cookie
雖然Cookie是服務端告訴客戶端瀏覽器需要保存內容,但是客戶端瀏覽器可以選擇拒絕保存,如果禁止自動保存Cookie那么只要是需要登錄的網站都沒辦法正常登錄了
- 視圖函數的返回值
return HttpResponse()
return render()
return redirect()
- 變形
obj = HttpResponse()
return objobj1 = render()
return obj1obj2 = redirect()
return obj2
如果想要操作Cookie,必須進行以上變形才可以
1.設置Cookie
obj = HttpResponse()
obj.set_cookie(key,value)
return obj
2.獲取Cookie
request.COOKIES.get(key)
3.設置超時時間
obj = HttpResponse()
obj.set_cookie(key,value,max_age=5)
# 設置超時時間 5s 到期
return obj
- max_age
- 設置超時時間,以秒為單位
- expiress
- 設置超時時間,針對IE瀏覽器使用,以秒為單位
4.注銷Cookie
obj = HttpResponse()
# 設置超時時間 5s 到期
obj.delete_cookie(key)
return obj
5.登錄功能實現
(1.0)簡單實現
- 路由
urlpatterns = [path('admin/', admin.site.urls),path('login/', views.login),path('home/', views.home),
]
- ?視圖
def login(request):if request.method == 'POST':username = request.POST.get('username')password = request.POST.get('password')if username == "dream" and password == "521":# 登陸成功之后,跳轉到登陸成功之后才能看到的頁面return redirect('/home/')return render(request, 'login.html')def home(request):return HttpResponse("登陸成功!")
- 前端
<form action="" method="post"><p>username:<input type="text" name="username" class="form-control"></p><p>password:<input type="password" name="password" class="form-control"></p><input type="submit" class="btn btn-success">
</form>
問題:登錄成功之后的跳轉頁面,不需要登錄也可以直接訪問到,只需要給對應的地址即可
(2.0)解決登錄問題
from django.shortcuts import render, HttpResponse, redirect# Create your views here.
def login(request):if request.method == 'POST':username = request.POST.get('username')password = request.POST.get('password')if username == "dream" and password == "521":# 登陸成功之后,保存用戶登陸狀態obj = redirect('/home/')# 讓瀏覽器記錄cookieobj.set_cookie("sign", "1314521")'''瀏覽器不單單只是幫我們保存cookie而且在后面每次訪問的時候都會帶著cookie'''# 登陸成功之后,跳轉到登陸成功之后才能看到的頁面return objreturn render(request, 'login.html')def home(request):# 讀取攜帶的cookie,cookie正確登陸成功if request.COOKIES.get("sign") == "1314521":return HttpResponse("登陸成功!")# 讀取攜帶的cookie,cookie不正確跳轉到登陸頁面return redirect('/login/')
(3.0)迭代-登錄認證裝飾器
用戶如果沒有登錄的情況下想訪問一個需要登錄的頁面,那么先跳轉到登錄頁面,當用戶輸入正確的用戶名和密碼之后再跳轉到用戶之前想訪問的頁面去,而不是直接寫死
from django.shortcuts import render, HttpResponse, redirect# Create your views here.
def login(request):if request.method == 'POST':username = request.POST.get('username')password = request.POST.get('password')if username == "dream" and password == "521":# 獲取用戶上一次想要訪問的url# 結果可能為空 -- 直接訪問logintag_url = request.GET.get('tag_url')if tag_url:obj = redirect(tag_url)else:# 登陸成功之后,保存用戶登陸狀態obj = redirect('/home/')# 讓瀏覽器記錄cookieobj.set_cookie("sign", "1314521")'''瀏覽器不單單只是幫我們保存cookie而且在后面每次訪問的時候都會帶著cookie'''# 登陸成功之后,跳轉到登陸成功之后才能看到的頁面return objreturn render(request, 'login.html')# 校驗用戶登錄狀態的裝飾器
def auth_check(func):def inner(request, *args, **kwargs):# 獲取到用戶上一次想要訪問的urltag_url = request.get_full_path()# 讀取攜帶的cookie,cookie正確登陸成功if request.COOKIES.get("sign") == "1314521":res = func(request, *args, **kwargs)return reselse:# 讀取攜帶的cookie,cookie不正確跳轉到登陸頁面return redirect(f'/login/?next={tag_url}')return inner@auth_check
def home(request):return HttpResponse("home登陸成功!")@auth_check
def index(request):return HttpResponse("index登陸成功!")@auth_check
def func(request):return HttpResponse("func登陸成功!")
四.Django操作Session
Session數據是保存在服務端的,給客戶端返回的是一個隨機字符串
1.設置Session
request.session['key'] = value
2.獲取Session
request.session.get('key')
3.設置/獲取Session多個值
- 給session設置多個值的時候存在數據庫中的數據仍是一條
- 但是在取session的時候,可以通過request.session對象獲取到設置的多組鍵值對
4.django_session表中的session數據
- django_session表中的數據條取決于瀏覽器
- 同一個計算器(IP地址)上同一個瀏覽器只會有一條數據失效
- 同一個計算器(IP地址)上多個瀏覽器會有多個數據生效
- 當session過期的時候可能會出現多條數據對應一個瀏覽器
- 但是這些數據不會持久化存儲,會被定時清理掉,可以手動清除也可以代碼清除
- 目的是為了節省服務器數據庫資源
5.設置過期時間
# 設置session
request.session['key'] = value
# 設置過期時間
request.session.set_expiry()
- 參數
- 整數
- 多少秒過期
- 日期對象
- 到指定日期失效
- 0
- 一旦退出當前瀏覽器窗口就失效
- 不寫
- 失效時間取決于Django內部全局session失效的時間
- 整數
6.清空session
(1)request.session.delete():
只刪除服務端的
該方法用于刪除當前用戶的Session數據,但是會保留Session的Key,這意味著Session對象本身仍然存在,但其中的數據將被清空,下次訪問時,如果Session沒有被重新填充則會得到一個空的Session對象
def clear_session(request):request.session.delete()# 其他操作或返回響應
???????(2)request.session.flush():
服務端和客戶端都刪除
該方法用于完全刪除當前用戶的Session,包括Session對象的所有相關數據,下次訪問時將創建一個新的空Session對象
def clear_session(request):request.session.flush()# 其他操作或返回響應
7.保存
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' # 引擎其他公用設置項:
SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串(默認)
SESSION_COOKIE_PATH = "/" # Session的cookie保存的路徑(默認)
SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默認)
SESSION_COOKIE_SECURE = False # 是否Https傳輸cookie(默認)
SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http傳輸(默認)
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默認)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否關閉瀏覽器使得Session過期(默認)
SESSION_SAVE_EVERY_REQUEST = False # 是否每次請求都保存Session,默認修改之后才保存(默認)
原理剖析
- *request*.session['sign'] = '369'內部發生了哪些事
- Django內部會自動幫我們生成一個隨機字符串
- Django自動將隨機字符串和對應的數據存儲到django_session表中
- 先在內存中產生操作數據的內存
- 在響應經過Django中間件的時候才去操作數據庫
- 將產生的隨機字符串返回給客戶端瀏覽器保存
- request.session.get('sign')內部發生了哪些事
- 自動從瀏覽器中獲取sessionid對應的隨機字符串
- 根據該隨機字符串去django_session表中查找對應的數據
- 如果匹配成功,則將對應的數據取出并以字典的形式封裝到request.session中
- 如果匹配不成功,則request.session中的數據為None
案例演示
(1.0)簡單的
- 路由
# session操作
path('set_session/', views.set_session),
- 視圖
def set_session(request):request.session['sign'] = "369"return HttpResponse("返回消息")
- 會報錯
OperationalError at /set_session/
no such table: django_session
- 數據是保存在服務端的
- 在默認情況下操作session的時候需要Django默認的一張django_session表
- 數據庫遷移命令時
- Django會默認創建很多表,其中就有Django_session表
- Django默認session的過期時間是14天
- 但是我們可以人為的修改過期時間
(2.0)解決方法
- 先進行數據庫遷移命令
- 再進行訪問
- session會自動保存到django_session表中
(3.0)優化
- 路由
# session操作
path('set_session/', views.set_session),
path('get_session/', views.get_session),
- 視圖
def set_session(request):request.session['sign'] = "369"return HttpResponse("返回消息")def get_session(request):request.session.get("sign")return HttpResponse("拿取成功消息")