Cookie和session


 

摘要:
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.安全性好,數據存在服務端
壞處:
數據都保存在服務端,存儲壓力比較大
 





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM