django框架之cookie/session的使用示例(小結(jié))
一、http協(xié)議無狀態(tài)問題
http協(xié)議沒有提供多次請求之間的關(guān)聯(lián)功能,協(xié)議的本意也并未考慮到多次請求之間的狀態(tài)維持,每一次請求都被協(xié)議認(rèn)為是一次性的。但在某些場景下,如一次登錄多次訪問,我們希望可以保存登錄狀態(tài),協(xié)議并沒有直接提供會(huì)話跟蹤的支持,需要靠其他手段來幫助實(shí)現(xiàn)目標(biāo)。
二、會(huì)話跟蹤技術(shù)--cookie
1、對cookie的理解
- cookie是一個(gè)key-value的數(shù)據(jù)結(jié)構(gòu)(類似python字典),用于保存需要維護(hù)狀態(tài)的數(shù)據(jù),cookie與session最大的區(qū)別是cookie的數(shù)據(jù)保存在客戶端,而session把數(shù)據(jù)保存在服務(wù)端。
- cookie一般由服務(wù)器設(shè)置,并可以存放在http的請求頭和響應(yīng)頭中。
- cookie由瀏覽器保存,瀏覽器已經(jīng)實(shí)現(xiàn)了cookie的保存和發(fā)送,而服務(wù)器上對cookie的設(shè)置和接收則需要我們配置。
- 通過cookie,可以在多個(gè)會(huì)話之間共享一些必要的信息如登錄狀態(tài)數(shù)據(jù)、歷史訪問記錄、個(gè)性化定制設(shè)置等,以實(shí)現(xiàn)會(huì)話跟蹤,讓用戶感覺到網(wǎng)站可以'記錄'自己的偏好,減少不必要的重復(fù)輸入,從而提升用戶體驗(yàn)。
2、cookie的使用接口
django的服務(wù)端發(fā)送響應(yīng)有三種方式:
1. return HttpResponse()
2. return render()
3. return redirect()
這三種方法實(shí)例化的結(jié)果都是HttpResponse類的實(shí)例,可以直接用于設(shè)置cookie。
在response對象上執(zhí)行set_cookie(key,value,...)即可設(shè)置cookie, 其中特別注意cookie屬性的設(shè)置。
cookie的設(shè)置
服務(wù)器在響應(yīng)對象上進(jìn)行set_cookie操作,一旦設(shè)置完成,客戶端后續(xù)的請求就可以根據(jù)cookie的屬性規(guī)則攜帶cookie數(shù)據(jù)。
def set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=False, httponly=False, samesite=None)
cookie的獲取
服務(wù)器在請求對象上通過request.COOKIES得到cookie字典數(shù)據(jù),注意此處拿到的cookie數(shù)據(jù)從安全性來說是未被驗(yàn)證正確性的。
@cached_property def COOKIES(self): raw_cookie = get_str_from_wsgi(self.environ, 'HTTP_COOKIE', '') return parse_cookie(raw_cookie)
注意1:cookie在set的時(shí)候可以設(shè)置它被發(fā)送的范圍,每個(gè)cookie都有對應(yīng)的domain+path的屬性,這約束了cookie發(fā)送范圍,只有當(dāng)http的請求落在此范圍中的url,才會(huì)攜帶此cookie。
注意2:一個(gè)cookie就是一個(gè)key-value項(xiàng),不過它還攜帶有屬性。一個(gè)cookies是一個(gè)字典,保存了很多cookie項(xiàng),注意單個(gè)cookie項(xiàng)和整個(gè)cookies字典的關(guān)系。
3、cookie的屬性
max_age:
失效延遲時(shí)間,單位是秒,設(shè)置成15秒意味著在設(shè)置完之后的15秒之內(nèi),此cookie有效,超時(shí)之后cookie失效,瀏覽器會(huì)刪除失效的cookie。此參數(shù)默認(rèn)是None,代表著直到瀏覽器關(guān)閉,即默認(rèn)是會(huì)話cookie。
注意:如果max_age是0,意味著讓瀏覽器立刻刪除此cookie,即此cookie即刻失效。
expires:
指定失效日期,同樣用于失效cookie,只不過是另一種時(shí)間指定方式。
domain:
此cookie可以被使用的域名范圍。
path:
與domain配合著使用,默認(rèn)是根路徑'/',意味著在當(dāng)前domain范圍下任何url都會(huì)攜帶此cookie??梢灾鲃?dòng)設(shè)置其他的路徑以縮小發(fā)送的范圍,從而約束某一個(gè)cookie項(xiàng)只應(yīng)用于某些url。
secure:
默認(rèn)是False,一般配合https協(xié)議使用,在https協(xié)議下,只有secure屬性是True的cookie才允許被發(fā)送。
httponly:
默認(rèn)是False,這意味著js也可以通過document.cookie來訪問和設(shè)置此cookie,而如果設(shè)置為True,則代表只允許服務(wù)端來訪問和設(shè)置此cookie。
4、使用cookie的問題
cookie的安全性問題
服務(wù)器是根據(jù)客戶端發(fā)送過來的cookie進(jìn)行狀態(tài)判斷,這種保存在客戶端的cookie數(shù)據(jù)非常容易修改和偽裝,服務(wù)器基本無法知曉cookie的正確性,也就不能100%信任cookie的數(shù)據(jù)。
此外,cookie很容易被盜取,如果客戶端cookie里面包含私密數(shù)據(jù)的話,就更不安全了。
cookie的覆蓋問題
在服務(wù)端上設(shè)置的新的cookie會(huì)讓客戶端更新本地cookie。
cookie的合理性問題
什么樣的數(shù)據(jù)適合放到cookie中?
cookie中的數(shù)據(jù)是每次交互都要被傳輸?shù)?,所以我認(rèn)為:
- 應(yīng)該是常用的數(shù)據(jù),如果不常用只會(huì)浪費(fèi)帶寬減少效率,最好是多次交互中都要使用或者修改
- 應(yīng)該是小數(shù)據(jù)量
- 不應(yīng)該是非常私密的數(shù)據(jù),否則:要么在客戶端上容易被盜取,要么在傳輸中容易被截取
所以cookie特別適合發(fā)送sessionid,它能滿足上述所有條件。
cookie的存儲(chǔ)問題
cookie是客戶端臨時(shí)存儲(chǔ),按規(guī)定單個(gè)cookie文件存儲(chǔ)量最大是4kb,每個(gè)域下的cookie文件不能超過20個(gè),不應(yīng)該將cookie作為存儲(chǔ)功能的濫用,要使用客戶端存儲(chǔ)功能應(yīng)該啟用localstorage。
cookie的訪問限制問題
js的document.cookie可以獲取cookie數(shù)據(jù),將會(huì)在控制臺輸出一個(gè)字符串格式的key-value數(shù)據(jù),如果此cookie的屬性是httponly=true就不能通過此方法獲取。
三、會(huì)話跟蹤技術(shù)--session
1、對session的理解
session把數(shù)據(jù)存放在服務(wù)器上,并使用一個(gè)標(biāo)簽session-key唯一標(biāo)記此數(shù)據(jù)。session-key作為cookie發(fā)送給客戶端,即客戶端只保存session-key,然后通過cookie發(fā)送給服務(wù)端,以表明身份,所以session比cookie安全。
每一次請求到達(dá)服務(wù)器的時(shí)候,服務(wù)器獲取cookie中保存的session-key,并在數(shù)據(jù)庫django-session表中尋找對應(yīng)的session-data,進(jìn)一步處理業(yè)務(wù)邏輯。
session的使用有如下優(yōu)點(diǎn):
1、數(shù)據(jù)保存在服務(wù)端,客戶端僅保存一個(gè)senssionid
2、sessionid數(shù)據(jù)量很小,適合每次發(fā)送
3、安全性,sessionid是一個(gè)隨機(jī)字符串,不攜帶任何私密數(shù)據(jù)
2、session的使用接口
session的設(shè)置
django實(shí)現(xiàn)了session,幫我們完成了很多操作,且提供使用的接口非常簡單:
request.session['name'] = 'xxx'
設(shè)置session的時(shí)候會(huì)執(zhí)行如下三個(gè)操作:
1、創(chuàng)建一個(gè)隨機(jī)字符串作為sessionid
2、把sessionid作為session-key,以及一個(gè)session_data字典加入到django-session表中
3、set-cookie,把sessionid發(fā)送給客戶端
注意1:從底層源碼來看,session_data其實(shí)就是一個(gè)字典{},然后通過orm存到django_session表中(應(yīng)該有dict-->str的序列化和加密操作)
注意2:如果發(fā)現(xiàn)客戶端的cookie中含有seesionid說明不是第一次登錄,將會(huì)使用此sessionid并更新此sessionid對應(yīng)的session_data數(shù)據(jù)
注意3:如果有兩個(gè)用戶在同一臺電腦的同一個(gè)瀏覽器上,訪問同一個(gè)url,因?yàn)閟essionid是作為cookie存在,所以兩個(gè)人會(huì)使用同一個(gè)sessionid。
而對于服務(wù)器而言,只認(rèn)sessionid不認(rèn)人,使用同一個(gè)sessionid的操作會(huì)覆蓋之前的數(shù)據(jù)以導(dǎo)致在服務(wù)端上的session_data數(shù)據(jù)會(huì)相互覆蓋,這樣的結(jié)果是數(shù)據(jù)紊亂(尤其當(dāng)兩人的數(shù)據(jù)項(xiàng)目數(shù)量不一致時(shí)更嚴(yán)重)
session的讀取
讀取session的接口同樣很簡單:
name = request.session['name']
讀取的時(shí)候會(huì)執(zhí)行如下三個(gè)操作:
1、獲取request.COOKIES中的sessionid
2、拿著sessionid作為session_key到數(shù)據(jù)庫的django-session表中查找對應(yīng)的session-data,底層就是執(zhí)行orm的objects.filter(session_key=sessionid)
3、獲取session-data中的數(shù)據(jù)并進(jìn)一步處理
session的刪除
刪除session的接口:
1、del request.session[xxx] # 刪除一個(gè)會(huì)話數(shù)據(jù)屬性
2、request.session.flush() # 刪除所有會(huì)話數(shù)據(jù)
清空會(huì)話信息時(shí)會(huì)執(zhí)行如下操作:
1、刪除django-session表中的session-key=sessionid的記錄,底層操作就是執(zhí)行orm的objects.filter(session_key=sessionid).delete()
2、刪除response中的cookie里的sessionid記錄
注意1:服務(wù)器把sessionid作為cookie的數(shù)據(jù)發(fā)給客戶端保存,一般是會(huì)話cookie即不關(guān)閉瀏覽器程序就可以一直保持會(huì)話跟蹤。但一旦客戶端關(guān)閉了瀏覽器,則此sessionid便不再有效。但django頒發(fā)的cookie默認(rèn)有效時(shí)間是2周,所以cookie會(huì)被保存到客戶端硬盤上,即使關(guān)閉了瀏覽器也繼續(xù)保存。
注意2:因?yàn)榉?wù)器無法獲知客戶端瀏覽器將會(huì)在什么時(shí)候關(guān)閉,更無法獲知瀏覽器什么時(shí)候會(huì)執(zhí)行清空cookie的操作。客戶端一般只有在logout的時(shí)候才會(huì)主動(dòng)告知?jiǎng)h除session,其他情況下瀏覽器不會(huì)主動(dòng)告知,所以服務(wù)器的session不能無限保存,被迫要設(shè)置失效時(shí)間(不然存儲(chǔ)空間浪費(fèi)),在一定時(shí)間內(nèi)如果還沒有用戶重新訪問此session,便被服務(wù)端認(rèn)為此用戶已失效,進(jìn)而可以刪除session數(shù)據(jù)。
3、session的屬性
settings中還可以配置全局的session屬性:
# settings.py文件 SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默認(rèn)) SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在瀏覽器上時(shí)的key,即:sessionid=隨機(jī)字符串(默認(rèn)) SESSION_COOKIE_PATH = "/" # Session的cookie保存的路徑(默認(rèn)) SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默認(rèn)) SESSION_COOKIE_SECURE = False # 是否Https傳輸cookie(默認(rèn)) SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http傳輸(默認(rèn)) SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默認(rèn)) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否關(guān)閉瀏覽器使得Session過期(默認(rèn)) SESSION_SAVE_EVERY_REQUEST = False # 是否每次請求都保存Session,默認(rèn)修改之后才保存(默認(rèn))
4、使用session的問題
1、session的正常工作依賴于cookie的啟用,如果客戶端禁用cookie功能,該如何保證session正常工作?---重寫URL
2、同一臺電腦同一個(gè)瀏覽器,訪問同一個(gè)url,保存著同一個(gè)sessionid,如何處理多用戶使用同一sessionid登錄而導(dǎo)致的數(shù)據(jù)紊亂問題?---使用用戶認(rèn)證組件,使用賬戶密碼來區(qū)別用戶
四、總結(jié)
1、cookie和session都是為了解決http協(xié)議自身并不支持狀態(tài)維持的缺點(diǎn)。
2、會(huì)話跟蹤的目的是為了讓多次請求之間可以共享數(shù)據(jù),以提供更好的用戶體驗(yàn)。
3、cookie和session都需要保存狀態(tài)維持?jǐn)?shù)據(jù),只不過cookie是保存在客戶端,session是保存在服務(wù)端。
4、分析和研究兩者的技術(shù)相同點(diǎn)和區(qū)別有助于加深對會(huì)話跟蹤的理解和使用。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python3使用tracemalloc實(shí)現(xiàn)追蹤mmap內(nèi)存變化
這篇文章主要為大家詳細(xì)介紹了在Python3中如何使用tracemalloc實(shí)現(xiàn)追蹤mmap內(nèi)存變化,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2023-03-03Python入門教程(三十九)Python的NumPy安裝與入門
這篇文章主要介紹了Python入門教程(三十九)Python的NumPy安裝與入門,NumPy 是一個(gè)Python包,它是一個(gè)由多維數(shù)組對象和用于處理數(shù)組的例程集合組成的庫,,需要的朋友可以參考下2023-05-05pandas數(shù)據(jù)處理基礎(chǔ)之篩選指定行或者指定列的數(shù)據(jù)
這篇文章主要介紹了pandas數(shù)據(jù)處理基礎(chǔ)之篩選指定行或者指定列的數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下2018-05-05python爬蟲Scrapy框架:媒體管道原理學(xué)習(xí)分析
這篇文章主要介紹了python爬蟲Scrapy框架:媒體管道原理學(xué)習(xí)分析,有需要的朋友可以借鑒參考,希望可以對廣大一同學(xué)習(xí)的讀者朋友有所幫助2021-09-09Python數(shù)據(jù)結(jié)構(gòu)之雙向鏈表的定義與使用方法示例
這篇文章主要介紹了Python數(shù)據(jù)結(jié)構(gòu)之雙向鏈表的定義與使用方法,結(jié)合實(shí)例形式分析了Python雙向鏈表的概念、原理、使用方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下2018-01-01基于python + django + whoosh + jieba 分詞器實(shí)現(xiàn)站內(nèi)檢索功能
這篇文章主要介紹了基于python + django + whoosh + jieba 分詞器實(shí)現(xiàn)站內(nèi)檢索功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08