摘要:
cookie和session的區別:
1.cookie:
cookie是保存在瀏覽器端的鍵值對,可以用來做用戶認證
2.session:
將用戶的會話信息保存在服務端,key值是隨機產生的字符串,value值是session的內容
依賴於cookie將每個用戶的隨機字符串保存到用戶瀏覽器上
Django中session默認保存在數據庫中:django_session表
flask,session默認將加密的數據寫在用戶的cookie中
Cookie
在一個會話的多個請求中共享數據,就是會話跟蹤技術
HTTP協議是無狀態協議,每個請求都是獨立的!無法記錄前一次請求的狀態。
但HTTP協議中可以使用Cookie來完成會話跟蹤!
在Web開發中,使用session來完成會話跟蹤,session底層依賴Cookie技術
Cookie的概念:
Cookie具體指的是一段小信息,它是服務器發送出來存儲在瀏覽器上的一組組鍵值對
Cookie的原理:
1.客戶端向服務端發送請求,第一次的值為空 cookie:{}
2.服務端接受請求后,設置cookie,request.set_cookie(key,value,),隨着響應發給瀏覽器
3.客戶端瀏覽器會把Cookie保存起來,當下一次再訪問服務器時把Cookie再發送給服務器
當客戶端向服務器發出請求時會把所有這個服務器Cookie包含在請求中發送給服務器,這樣服務器就可以識別客戶端了!
Cookie與HTTP頭 :
Cookie是通過HTTP請求和響應頭在客戶端和服務器端傳遞的:
1.客戶端請求:
請求頭中攜帶Cookie:{key,value}
格式:Cookie: a=A; b=B; c=C。即多個Cookie用分號離開
2.服務端響應:
響應頭中攜帶Set-Cookie:{key,value}
一個Cookie對象一個Set-Cookie:
Set-Cookie:a=A Set-Cookie: b=B Set-Cookie: c=C
如果服務器端發送重復的Cookie那么會覆蓋原有的Cookie,例如客戶端的第一個請求服務器端發送的Cookie是:Set-Cookie: a=A;第二請求服務器端發送的是:Set-Cookie: a=AA,
那么客戶端只留下一個Cookie,即:a=AA。
1.設置Cookie
rep = HttpResponse(...)
rep = render(request, ...)
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密鹽',...) 加密
return rep
2.獲取cookie
request.COOKIES.get("is_login")
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
3.刪除Cookie
def logout(request):
# 如何刪除Cookie
rep = redirect("/login/")
rep.delete_cookie("is_login")
return rep
簡單的cookie操作
def login(request):
if request.method=="POST":
name=request.POST.get("username")
passwd=request.POST.get("password")
if name=="jerd" and passwd=="123":
##使用cookie,讓瀏覽器保存一個鍵值對
rep=redirect("/home/")
# rep.set_cookie("is_login","1") #明文
##使用密文##
rep.set_signed_cookie("is_login","1",salt="jerd")
return rep
return render(request,"login.html")
def home(request):
##進行判斷,如果登錄成功就能進入到家目錄,沒登錄,就去登錄
# ret=request.COOKIES.get("is_login") #傳過來的是字符串
ret=request.get_signed_cookie("is_login",default='0',salt="jerd")
if ret=="1":
return render(request, "home.html")
else:
return render(request, "login.html")
View Code
使用裝飾器
def is_login(func):
def inner(request,*args,**kwargs):
ret=request.get_signed_cookie("is_login",default='0',salt="jerd")
if ret == "1":
return func(request,*args,**kwargs)
else:
return render(request,"login.html")
return inner
@is_login
def index(request):
return render(request, "index.html")
View Code
Cookie版登陸校驗
如果是從其他頁面跳轉到登錄頁面,在登錄成功后,跳轉到之前的頁面
from functools import wraps
def is_login(func):
@wraps(func) # 裝飾器修復技術
def inner(request,*args,**kwargs):
ret=request.get_signed_cookie("is_login",default='0',salt="jerd")
if ret == "1":
return func(request,*args,**kwargs)
else:
now_url=request.path_info #獲取當前訪問的url
return redirect("/login/?next={}".format(now_url))
return inner
def login(request):
print("-" * 120)
print(request.get_full_path()) # 獲取當前請求的路徑和參數
print(request.path_info) # 取當前請求的路徑
print("-" * 120)
if request.method=="POST":
name=request.POST.get("username")
passwd=request.POST.get("password")
next_url = request.GET.get("next") # 從URL里面取到 next 參數
print(next_url)
if name=="jerd" and passwd=="123":
##使用cookie,讓瀏覽器保存一個鍵值對
##如果是從其他頁面跳轉到登錄頁面,在登錄成功后,跳轉到之前的頁面
if next_url:
rep = redirect(next_url)
#直接進登錄頁面,登陸后,默認跳到home頁面
else:
rep=redirect("/home/")
# rep.set_cookie("is_login","1") #明文
##使用密文 一周有效##
rep.set_signed_cookie("is_login", "1", salt="jerd",max_age=7*24*60*60)
return rep
return render(request,"login.html")
def home(request):
##進行判斷,如果登錄成功就能進入到家目錄,沒登錄,就去登錄
# ret=request.COOKIES.get("is_login") #傳過來的是字符串
ret=request.get_signed_cookie("is_login",default='0',salt="jerd")
if ret=="1":
return render(request, "home.html")
else:
return render(request, "login.html")
@is_login
def index(request):
return render(request, "index.html")
##刪除cookie##
def logout(request):
rep=redirect("/login/")
rep.delete_cookie("is_login")
return rep
在登錄頁面中,就不能再提交給login
{#從其他頁面跳到登錄頁面時,此時login后面帶有參數,提交時就不能再提交給login#}
{#<form action="/login/" method="post">#}
<form action="{{ request.get_full_path }}" method="post">
View Code
Session
Cookie彌補了HTTP無狀態的不足,讓服務器知道來的人是“誰”;但是Cookie本身保存在客戶端,可能被攔截或竊取,自身安全性較差;
而Session保存在服務器,有較高的安全性。
所以我們就通過Cookie識別不同的用戶,對應的在Session里保存私密的信息
session的特性:
Session是服務器端技術,服務器在運行時可以為每一個用戶的瀏覽器創建一個其獨享的session對象,
由於session為用戶瀏覽器獨享,所以用戶在訪問服務器的web資源時,可以把各自的數據放在各自的session中,
當用戶再去訪問該服務器中的其它web資源時,其它web資源再從用戶各自的session中取出數據為用戶服務。



Session的類型
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
]
Django中默認支持Session,其內部提供了5種類型的Session供開發者使用:
1.數據庫(默認)
2.緩存
3.文件
4.緩存+數據庫
5.加密cookie
1、數據庫Session:Django默認將Session數據存到數據庫中,在django_session表中
配置settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默認)
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,默認修改之后才保存(默認)
2.緩存session:將session放到緩存中
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的緩存別名(默認內存緩存)
SESSION_COOKIE_NAME = "sessionid"
3.文件session:將session放到文件中
SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎
SESSION_FILE_PATH = None # 緩存文件路徑,如果為None,則使用tempfile模塊獲取一個臨時地址
SESSION_COOKIE_NAME = "sessionid"
4.緩存+數據庫Session
數據庫用於做持久化,緩存用於提高效率
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'
5.加密cookie Session:將session加密后放到cookie中(flask就是這樣的)
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
常用操作:
1.設置session: request.session["is_login"]="1"
2.獲取session: request.session.get(""is_login")
3.只刪除session數據 request.session.delete()
4.刪除session數據和cookie request.session.flush()
5.設置會話Session和Cookie的超時時間
request.session.set_expiry(value)
* 如果value是個整數,session會在些秒數后失效。 cookie值消失
* 如果value是個datatime或timedelta,session就會在這個時間后失效。
* 如果value是0,用戶關閉瀏覽器session就會失效。
* 如果value是None,session會依賴全局session失效策略。
6.在setting中添加
SESSION_SAVE_EVERY_REQUEST =True 每次請求都保存Session設置后,如果存在數據庫中,需要遷移數據庫
使用makemigrations和migrate后,數據庫中會澤東生成一張session表,存放着k和data
Session版登陸驗證
from functools import wraps
def is_login(func):
@wraps(func) # 裝飾器修復技術
def inner(request,*args,**kwargs):
ret=request.session.get("is_login")
#獲取時的流程##
# 1. 獲取cookie中的隨機字符串
# 2. 根據隨機字符串去數據庫取 session_data --> 解密 --> 反序列化成字典
# 3. 在字典里面 根據 is_login 取具體的數據
if ret == "1":
return func(request,*args,**kwargs)
else:
now_url=request.path_info #獲取當前訪問的url
return redirect("/login/?next={}".format(now_url))
return inner
def login(request):
print("-" * 120)
print(request.get_full_path()) # 獲取當前請求的路徑和參數
print(request.path_info) # 取當前請求的路徑
print("-" * 120)
if request.method=="POST":
name=request.POST.get("username")
passwd=request.POST.get("password")
next_url = request.GET.get("next") # 從URL里面取到 next 參數
if name=="jerd" and passwd=="123":
if next_url:
rep = redirect(next_url)
#直接進登錄頁面,登陸后,默認跳到home頁面
else:
rep=redirect("/home/")
request.session["is_login"]="1"
##可以設置多個值,但都存在一個k只 k:{"is_login":"1","name":user}
request.session.set_expiry(100) # 100秒鍾之后失效
request.session["name"] = name
return rep
return render(request,"login.html")
@is_login
def home(request):
user=request.session.get("name") #獲取到用戶名
return render(request, "home.html",{"username":user})
@is_login
def index(request):
return render(request, "index.html")
##刪除##
def logout(request):
request.session.flush()
return redirect("/login/")
View Code
cookie和session總結
1.COOKIE的由來:
因為HTTP請求時沒有狀態的,每一次請求都是獨立的,它不會受前面的請求響應情況直接影響,也不會直接影響后面的請求響應情況。
2.cookie就是保存在瀏覽器上的鍵值對
服務器控制着響應,在響應里可以讓瀏覽器在本地保存鍵值對,下次請求再發送的時候就會自動攜帶這個cookie值。瀏覽器關閉,cookie就失效
3.cooie的應用:1.七天免登陸 2.記錄用戶的瀏覽器習慣 3.簡單的投票規則
4.服務端:
1. 生成字符串
2. 隨着響應將字符串回復給瀏覽器
3. 從瀏覽器發送的請求中拿到字符串
好處:
服務端不用存,減輕了服務器壓力
壞處:
信息不安全
session:保存在服務端的鍵值對,必須依賴於cookie
在服務器端存在的形式 sadsjhsjkcehhw:{"is_login":1,"user":"jerd"}
Django中session的執行存過程:
存session: request.session["is_login"]="1"
1.在服務端生成隨機字符串
2.生成一個和上面隨機字符串對應的大字典,用來保護疏忽數據
3.隨機字符串當成cookie返回給瀏覽器
取session:ret=request.session.get("is_login")
1.從請求攜帶的cookie里面找到隨機字符串
2.拿到的隨機字符串去session中找對應的大字典
3.從大字典中根據key取值
session的優勢:
1.比cookie能存的數據多
2.安全性好,數據存在服務端
壞處:
數據都保存在服務端,存儲壓力比較大