拜托!不要再問我Session與Cookie的區(qū)別了
在 Web 開發(fā)里面有一個(gè)歷久不衰的議題,那就是 Session 與 Cookie 的區(qū)別。
從我剛開始學(xué)程序時(shí)這一題就常出現(xiàn)在面試考題里,一直到現(xiàn)在都還是能看見這個(gè)問題。
這個(gè)問題重要嗎?我覺得蠻重要的。因?yàn)?Session 所代表的是「狀態(tài)」,如果沒有了狀態(tài),一大堆功能都會失效。
對于工程師來說必須去理解什么是 Session,以及如何操作它,而 Cookie 就是這之中很重要的一環(huán)。
因此這會是一系列的文章,我稱之為 Session 與 Cookie 三部曲,會由淺入深,從不同的面向去看 Session 與 Cookie。
這是系列文的第一篇,想用簡單白話的方式通俗地跟大家解釋什么是 Session,什么又是 Cookie,目標(biāo)是希望沒有任何技術(shù)背景的人也能夠看懂。
要向沒有技術(shù)背景的人講這種概念性的東西,用一堆專有名詞絕對是最差勁的做法。
而最好的做法通常是舉一個(gè)現(xiàn)實(shí)生活中很貼近的例子,藉由這種方式比較能讓毫無技術(shù)背景的讀者們?nèi)ダ斫膺@到底是個(gè)什么東西。
因此,我們從經(jīng)營雜貨店開始吧!
小明の雜貨店
四十歲的小明退休以后在家閑得發(fā)慌,每一天都過得毫無目標(biāo)而且渾渾噩噩。
「退休以后不是應(yīng)該無憂無慮嗎?」小明也是這樣問自己的,但沒辦法,他深知自己的個(gè)性就是這樣,沒辦法閑下來,一定要做點(diǎn)事情才行。
于是,小明就用了退休金在家里附近的巷口開了間雜貨店,并且取名為:「小明の雜貨店」,是個(gè)毫無創(chuàng)意的名稱,但把自己的名字放在招牌上一直是他的夢想。
小明平時(shí)人緣還算不錯(cuò),在倒垃圾時(shí)會與旁邊的婆婆媽媽閑聊,說著那個(gè)誰誰誰的兒子考上了臺大,誰誰誰的女兒最近交了個(gè)男友,成為左鄰右舍八卦網(wǎng)絡(luò)的一部分。
不只婆婆媽媽,連年輕的那一代也對他感覺不錯(cuò),八成是因?yàn)樗茏R相地不會硬要跟年輕人尬聊,看到他們都只是簡單點(diǎn)個(gè)頭示意一下,而不是像其他人劈頭就把私事全都問了一遍。
因此在開幕那天,雜貨店好比 Apple Store 開幕一般(除了沒有人特地前一天就跑來排隊(duì)以外),周遭的鄰居們都跑來捧場,把整個(gè)店擠得水泄不通,單日營收甚至上百萬(臺幣)。
第一天就能有如此成績,可見人緣是多么重要的一件事。有人緣,有人潮;有人潮,有錢潮。
但開幕畢竟是開幕,通常都是一家商店這輩子的巔峰,除非有跳樓大拍賣(假的那種不算,例如說每天都在大拍賣的)或是周年慶,不然都很難超越了。
隨著日歷一張張被撕開,店里的生意慢慢恢復(fù)正常,還是喜歡傳統(tǒng)便利商店的都跑回去便利商店了,而嫌遠(yuǎn)懶得走這么多路的則選擇雜貨店消費(fèi)。
看似步上正軌的雜貨店,問題卻隨著時(shí)間慢慢浮上臺面。
臉盲癥的困擾
小明身為雜貨店的店長兼唯一的店員,所有大小事都是他一個(gè)人在處理。傳統(tǒng)雜貨店跟便利商店最大的差別在哪里?在于人情味。
就像是你去菜市場買菜的時(shí)候會被說帥哥或美女,或者是去買早餐的時(shí)候老板會問你:「一樣?」,你只要點(diǎn)個(gè)頭就行了。這些人與人之間的情感是無論信息怎么發(fā)展都無法取代的。
可是小明沒有辦法,因?yàn)樗居洸黄饋硎峭粋€(gè)人。
每一個(gè)來店里的人對小明來說都是一個(gè)獨(dú)立的個(gè)體,是完全不相干的。你可能會疑惑說:「就算認(rèn)不出臉,認(rèn)聲音、衣服、氣味也都可以吧?」,看來你是太低估小明了。
小明不只認(rèn)不出臉,他什么都認(rèn)不出來。我也不知道小明到底哪里出了差錯(cuò),小明自己也不知道。
但總之就是這樣,就算你每天來,每天穿著一樣的衣服,用著一樣的聲音,他都認(rèn)不出來你是同一個(gè)人。
講一個(gè)例子你就知道了,有一次有個(gè)顧客結(jié)完帳以后把發(fā)票忘在柜臺,一出店門口才想起來,就立刻跑回去拿。
結(jié)果小明完全沒認(rèn)出來是同一個(gè)人,還以為這人是想來偷拿發(fā)票的,跟他確認(rèn)過買的品項(xiàng)一致以后才愿意把發(fā)票還給他。
對,就是這么夸張,小明每一次結(jié)賬都是在幫一個(gè)全新的人結(jié)賬。
在生活上或許沒什么問題,反正小明無依無靠也沒朋友,自己一個(gè)人生活慣了,可是在經(jīng)營雜貨店上面就有很大的問題了。
除了會讓人覺得很沒有人情味以外,最大的問題就是有些顧客的需求他沒辦法處理。
有些人逛雜貨店喜歡慢慢挑慢慢選嘛,然后有些物品可能又很重,或者是在結(jié)賬的時(shí)候才突然想起來還要買什么,這時(shí)候就會把東西先放在收銀臺那里,自己跑回去拿其他品項(xiàng)。
我前面已經(jīng)提過了,小明認(rèn)人的能力是零,當(dāng)客人拿新的物品回去收銀臺的時(shí)候,小明已經(jīng)認(rèn)不出他來了。
因此他不知道收銀臺上面那些物品是誰的,客人也很難跟小明證明說:「對,這些是我剛剛想買的」。
這個(gè)使用者體驗(yàn)簡直差到不行,因此店里的生意每況愈下,只有那種果斷型顧客會來消費(fèi)(一進(jìn)雜貨店就往自己的目標(biāo)走,拿完之后立刻結(jié)賬的那種)。
小明當(dāng)然注意到了這個(gè)狀況,也知道不能再這樣下去了,繼續(xù)這樣的話大概不用兩個(gè)月店就會倒了。于是小明左思右想,快思慢想,東想西想,終于想到了一個(gè)解決方法。
方法雖老舊但有用
前面有提到過小明最大的問題是「每個(gè)客人都是新的客人」,他沒辦法認(rèn)出他們是同一個(gè)客人,所以自然也無法記住他們的「狀態(tài)」,而這個(gè)才是最大的問題。
山不轉(zhuǎn)路轉(zhuǎn),路不轉(zhuǎn)頭轉(zhuǎn),既然小明自己沒辦法記住狀態(tài),寫張紙條不就得了嗎?
當(dāng)你在收銀臺結(jié)賬的時(shí)候?qū)懸粡埣垪l給你,上面寫著:「五香乖乖x1、義美鮮奶茶x1」,然后你就可以回去挑其他你想要的東西,當(dāng)你再回來收銀臺的時(shí)候把這張紙條給小明,小明就知道這些東西是你的。
或者你是個(gè)??停看蝸矶假I一樣的東西,小明就在結(jié)賬時(shí)寫給你一張紙條,把你常買的東西全都寫上去,這樣下次結(jié)賬時(shí)你只要帶那一張紙條過來,小明就知道你常買什么了!
你有看過那種凄美愛情電影嗎?男女主角其中一方得了罕見疾病,每天都會徹底失憶一次,另一方就會在家里幫他寫滿便條紙,透過那些便條紙,主角才能知道自己是誰、對方是誰,以及自己到底發(fā)生了什么事。
對,你可以把小明想象成就是失憶的那個(gè),而便條紙就是給客人的紙條。既然自己記不住,就讓這些紙條代勞,把狀態(tài)放在上面。
雖然說客人要把紙條留著其實(shí)蠻不方便的,但前面說過小明人緣其實(shí)不錯(cuò),因此??投紩丛谒拿孀由习鸭垪l帶著,讓這個(gè)機(jī)制得以繼續(xù)運(yùn)作。而小明店里的生意也因此好轉(zhuǎn)一點(diǎn)點(diǎn)。
對,只有一點(diǎn)點(diǎn)而已,因?yàn)殡S身攜帶一張紙條實(shí)在是太麻煩了,所以也沒多少人會這樣做。
再繼續(xù)往下講之前,我們先進(jìn)入中場休息。
中場休息
讓我們先從比喻回到網(wǎng)絡(luò)世界里,HTTP 是無狀態(tài)的,所以每一個(gè) Request 都是不相關(guān)的,就像是對小明來說每一位客人都是新的客人一樣,他根本不知道誰是誰。
既然你沒辦法把他們關(guān)聯(lián),就代表狀態(tài)這件事情也不存在。
把左邊換成顧客,右邊換成小明也依然成立。多一個(gè)得是我多打了,但我懶得修。
那怎么辦呢?在故事里我們用紙條來解決這件事情,小明會在結(jié)賬時(shí)寫下紙條并遞給客人,客人下次只要再帶著紙條過來,小明就知道發(fā)生什么事了。
小紙條功不可沒
小明最大的問題就是他自己沒辦法記憶「狀態(tài)」,因此需要倚靠一個(gè)機(jī)制來幫他管理「狀態(tài)」,而這個(gè)機(jī)制我們就叫做 Session。
原本對小明來說,每一個(gè)客人都是新的客人,彼此之間毫無關(guān)聯(lián),所以也沒有任何狀態(tài)可言。
但有了紙條以后,兩個(gè)在小明眼中完全不同的客人被關(guān)聯(lián)了起來,小明就可以知道:「原來這個(gè)新的客人是以前那個(gè)來買木材的客人!」
所以 Session 是什么?就是一種讓 Request 變成 Stateful 的機(jī)制。以小明的例子來說,Session 就是一種讓客人之間能互相關(guān)聯(lián)起來的機(jī)制。
小明靠紙條來實(shí)作 Session 機(jī)制,那在網(wǎng)絡(luò)世界中可以靠什么呢?舉一個(gè)最簡單的例子,網(wǎng)址!
讓我們假設(shè)有個(gè)購物網(wǎng)站的網(wǎng)址是:market.tw,當(dāng)你把蘋果加入購物車的時(shí)候,你其實(shí)是送一個(gè) Request 給服務(wù)器,然后服務(wù)器會把你導(dǎo)到 market.tw?
item1=apple,接著你再把火山硅肺病加入購物車,網(wǎng)址就會變成:market.tw?item1=apple&item2=pneumonoultramicroscopicsilicovolcanoconiosis
最后你按下結(jié)賬,服務(wù)器就靠著你地址欄上的信息來判斷你的狀態(tài)是什么,在這個(gè)例子中就等同于看你的購物車?yán)锩嬗惺裁础?/p>
簡單來說呢,地址欄上的信息就是小明故事中的紙條,是儲存狀態(tài)的地方。而上述例子 Client 與 Server 透過地址欄上的狀態(tài)來實(shí)作 Session 機(jī)制。
好,中場休息差不多到這邊要結(jié)束了。這一段是想先拉回網(wǎng)絡(luò)的部分,從原本故事中的比喻切回真實(shí)世界網(wǎng)絡(luò)的運(yùn)作模式,以及先讓大家理解 Session 到底是個(gè)什么東西。
在接下來的故事里面,小明會碰到更多更多的問題,他能迎刃而解嗎?讓我們繼續(xù)看下去。
到底誰會隨身攜帶紙條?
前面已經(jīng)有提過了,盡管小明靠著這個(gè)紙條的機(jī)制留住了一些???,但是新客人呢?有多少人會愿意為了再來這間店而特地留下具有狀態(tài)的紙條?
基本上沒有,因?yàn)檫@樣子太麻煩了!
有天小明在快要入眠時(shí),忽有一龐然大物拔山倒樹而來,蓋一靈感也。他想到了一個(gè)絕妙的 idea:「不會有人隨身攜帶紙條,但總會隨身攜帶手機(jī)吧!」
于是流程就變成這樣子:
- 客人來店里消費(fèi),小明結(jié)賬時(shí)請他拿出手機(jī),并在手機(jī)里面留了一些信息
- 客人第二次來店里,小明看看手機(jī)里有沒有之前自己留下的信息
先不用管到底小明把信息放在手機(jī)的哪里,這不是重點(diǎn);重點(diǎn)是手機(jī)里的信息取代了以前的紙條,客人不用刻意再帶一個(gè)沒有用的紙條了,只需要把本來就會隨身攜帶的手機(jī)拿出來就好,跟以前相比方便許多。
好,接下來我們終于要講到標(biāo)題的第二個(gè)東西了:Cookie。Cookie 是什么?Cookie 就是故事里面存在手機(jī)的信息。
想要知道真正使用 Cookie 的流程,你只要把上面的客人用「瀏覽器」來取代,小明用「服務(wù)器」來取代,就是答案了:
- 瀏覽器發(fā)送一個(gè) Request 給 Server,Server 叫瀏覽器設(shè)置 Cookie,瀏覽器便把這些數(shù)據(jù)存在 Cookie 里面。
- 瀏覽器帶著 Cookie 一起發(fā) Request 給 Server,Server 根據(jù) Cookie 的內(nèi)容決定狀態(tài)。
這次沒有買火山硅肺病了
雖然在現(xiàn)實(shí)生活中不是每個(gè)人都會隨身攜帶手機(jī),但是每個(gè)瀏覽器都會把 Cookie 一并帶上去,也會按照 Server 的指令來儲存 Cookie。
你可以把 Cookie 稱作是一個(gè)機(jī)制,Server 可以利用 Set-Cookie 這個(gè)語法讓瀏覽器儲存一些內(nèi)容,而這些內(nèi)容會在瀏覽器發(fā)送 Request 時(shí)一并送上來。
而瀏覽器里儲存的那些內(nèi)容也叫做 Cookie,就是我們故事中所提的小紙條或者是存在手機(jī)里的信息。
前面有提過 Session 機(jī)制可以只靠地址欄操作,跟 Cookie 可以一點(diǎn)關(guān)系都沒有。
但在實(shí)際應(yīng)用上,Session 之所以常常跟 Cookie 綁在一起,就是因?yàn)榭?Cookie 來操作 Session 機(jī)制的話非常方便。
或者應(yīng)該這樣說,Cookie 本來就是為了操作 Session 而生的。藉由標(biāo)準(zhǔn)化的規(guī)范,制定了一個(gè)專門用來讓瀏覽器與 Server 交換數(shù)據(jù)的機(jī)制。
如果用故事來比喻,就好比政府制定說每個(gè)人隨身一定要攜帶手機(jī),然后手機(jī)里面一定要存小明留下來的狀態(tài)。
這邊再來做個(gè)簡單的總結(jié):
Session 是什么?就是一種讓 Request 變成 Stateful 的機(jī)制。以小明的例子來說,Session 就是一種讓客人之間能互相關(guān)聯(lián)起來的機(jī)制。在故事里面我們用了紙條跟手機(jī)里的信息來比喻,有多種方式可以達(dá)成 Session。
在網(wǎng)絡(luò)世界中,也有很多種方式可以來操作 Session,前面介紹過第一種是地址欄,第二種就是靠 Cookie。而 Cookie 就是存在瀏覽器里的一些信息。
講到這邊,差不多就把 Session 與 Cookie 的定義與介紹講完了,但故事還沒完呢,我們還有最后一個(gè)問題要來解決。
咖啡寄杯的煩惱
雖然店里生意還可以,但小明無時(shí)無刻不想著怎么樣發(fā)大財(cái)賺大錢,讓店里的生意變得更好。
他觀察到最近好多便利商店開始賣起了咖啡,而且時(shí)不時(shí)就買一送一或是第二件半價(jià),并且貼心地提供了寄杯的服務(wù)。
寄杯就是指說你今天先喝一杯,剩下那杯我?guī)湍阌浿?,你下次來的時(shí)候跟我講我再給你。
如果不提供這種服務(wù),那買一送一就一定要兩個(gè)人才能喝了(或是你立刻喝兩杯),根本就是排擠像小明這樣的邊緣人。秉持著將心比心的原則,小明當(dāng)然是希望提供寄杯服務(wù)的。
那該怎么寄呢?照之前那樣不就得了嗎?原本客人的手機(jī)里面會存著消費(fèi)習(xí)慣之類的東西,現(xiàn)在多存一個(gè)還有幾杯咖啡不就行了?
例如說客人買兩杯只喝一杯,就在上面寫著:coffee=1,代表還剩一杯咖啡,下次來的時(shí)候只要出示這個(gè)信息,就再給他一杯。
聽起來十分合理,而且小明也這樣做了,店里的生意變得更好,買咖啡的人愈來愈多,靠著咖啡就讓單月營收翻了兩倍。
一切看似非常順利,直到小明月底對帳的時(shí)候:不對啊,為什么買咖啡的數(shù)量只有 55 杯,賣出去的卻有 66 杯?
一向很相信人的小明,在那一瞬間見識到了人心的險(xiǎn)惡之處。沒錯(cuò),有人自己偷改信息,例如說把 coffee=1 加個(gè)幾劃改成 coffee=7,就獲得了額外六杯的免費(fèi)咖啡。
這些奧步讓小明狠狠一夜之間變成了大人,絕望的小明把悲憤轉(zhuǎn)化成力量,只花了三個(gè)晚上就想到了兩個(gè)解決方法。
第一個(gè)方法最簡單,就是只要把存在客人手機(jī)上的信息加密就好了。
例如說原本是 coffee=1,經(jīng)過小明自制的特殊加密算法之后,會變成 ED85B89167A84B631C10B046B5FB7FC0 這串只有小明知道怎么解開的密文。
這樣一來,除非客人可以破解這段密碼,否則信息就不可能被竄改。但有一個(gè)小缺點(diǎn),那就是當(dāng)小明想存的信息愈來愈多之后,這一串字也會愈來愈長,就會在客人的手機(jī)里面占更大的容量。
這個(gè)容量是有上限的,客人不會把整臺手機(jī)都給你存這些信息,所以這點(diǎn)要特別注意。
這個(gè)方法解決問題的思路是這樣的:「既然存在手機(jī)上的信息會被竄改,那我讓他不能改就好」。
而第二個(gè)方法解決問題的思路是這樣的:「既然存在手機(jī)上的信息會被竄改,那我把信息存在我這邊不就好了嗎?」
與其把那些消費(fèi)習(xí)慣或是寄杯數(shù)量存在客人的手機(jī)里,不如把這些東西記在我的筆記本里面,并且用一種方式把這兩個(gè)信息對應(yīng)起來,這樣就不怕數(shù)據(jù)會被改動(dòng)了。
舉例來說,小明可以在筆記本寫下客人的身份證字號跟相關(guān)資訊,例如說:「A111111111 coffee=1」,接著小明只在客人的手機(jī)里面存「A111111111」。
下次客人再來消費(fèi)的時(shí)候,就透過身份證字號去筆記本里面查,就知道客人到底還剩幾杯咖啡了。
由于小明的筆記本每天下班都會鎖在保險(xiǎn)箱里面,因此不用害怕被偷或是被改,可以假設(shè)它一定是準(zhǔn)確的。
而這樣子的方式不把主要信息存在客人那里,而是存在自己這里,所以也不會有被竄改的風(fēng)險(xiǎn)。
可是有個(gè)問題,如果有人把身份證字號改成其他人的怎么辦?那不就破功了嗎?就可以偽造其他人的身份。
這個(gè)簡單,不如不要用身份證字號,用一個(gè) 16 位數(shù)的英數(shù)字混合亂碼好了,例如說:A59Uhe7I94J330mN,這樣就很難被猜到了吧!
于是流程會變成這樣:
客人那編只需要報(bào) ID 即可,其他資訊都在小明那里
跟之前一樣,他們都是透過一張紙條或者是手機(jī)里的信息來溝通,但唯一的差別是客人跟小明之間只透過 A59Uhe7I94J330mN 這個(gè)存在手機(jī)里的 ID 來驗(yàn)證身份,其他相關(guān)資訊都寫在小明的筆記本里面。
這種驗(yàn)證的方法就像是我曾經(jīng)去過的網(wǎng)咖。因?yàn)闀T打咖比較便宜嘛,一小 60 變成一小 36,不辦白不辦,就辦了一張會員卡。店員特別說明認(rèn)卡不認(rèn)人,一定要出示卡片才行。
我只要去打咖的時(shí)候出示這張會員卡,店員就知道我曾經(jīng)消費(fèi)過多少錢,也知道我喜歡點(diǎn)的餐點(diǎn),所有的信息都是存在他們的系統(tǒng)里面,而我的身份就是透過這張會員卡來表示。
寄杯的例子中,會員卡就是 A59Uhe7I94J330mN 這個(gè) ID,網(wǎng)咖的電腦系統(tǒng)就是小明的筆記本。
小明最后決定用第二種方法,也就是這種靠 ID 認(rèn)人的方式來管理客人的狀態(tài)。
從此之后就沒有客人能夠竄改信息了,而寄杯服務(wù)也運(yùn)行的十分順利,真是皆大歡喜,可喜可賀。
至于后來變得生意太好,讓小明開了分店以后碰到的那些問題,就又是另外一段故事了。
儲存狀態(tài)的方式
小明的故事說完了,該來把上面這一段變成網(wǎng)絡(luò)的實(shí)際案例了。其實(shí)在網(wǎng)絡(luò)世界中問題也是一樣的。
前面已經(jīng)提到過我們會把狀態(tài)存在 Cookie 里面,讓 Request 之間能夠變得有關(guān)聯(lián)。
假設(shè)我們今天要來做一個(gè)會員系統(tǒng),那我要怎么知道這個(gè) Request 代表的是哪一個(gè)會員?
最直覺的方式就是登入以后把會員帳號存在 Cookie 里面嘛,這樣不就知道是誰了嗎?
可是會碰到的問題就跟寄杯的故事一樣,Cookie 里的東西是可以被竄改的,如果我改成了別人的會員帳號,我就可以偽造他的身份登入了!
解決方法跟上面寄杯的解法一樣:
第一個(gè)解法就是把 Cookie 里面的內(nèi)容給加密,這樣就無法被竄改了。這種方式就稱之為 Cookie-based session,意思就是你把所有的 Session 狀態(tài)都存在 Cookie 里面。
所以不要把「用 Cookie 來操作 Session 機(jī)制」跟「Cookie-based session」搞混了,兩者是不一樣的。
至于缺點(diǎn)的話前面有提到,Cookie 的大小是有限制的,超過大小的話瀏覽器就不幫你存了。
因此當(dāng)你想存的信息越來越多,Cookie 當(dāng)然也越來越大,就有可能超過這個(gè)限制。
或者是哪天你的加密方式以及密鑰被黑客破解,那黑客一樣可以偽造任何人的身份。
第二個(gè)解法就是透過一個(gè) ID 來辨識身份,這個(gè) ID 稱之為 Session Identifier,簡稱 Session ID。
Server 只在 Cookie 里面存一個(gè) Session ID,其余的狀態(tài)都存在 Server 那邊,我習(xí)慣把 Server 那邊的數(shù)據(jù)稱為 Session Data:
其實(shí)就是小明筆記本的翻版而已
Session ID 的產(chǎn)生方式跟前面說的一樣,通常會是一個(gè)無法猜測的隨機(jī)數(shù)。
你可能會想說:「很難猜是一回事,但機(jī)率不是 0 啊!」,對,的確是有機(jī)率能夠猜到,但是那個(gè)機(jī)率太低太低了(例如說幾千億分之一之類的)。
而且 Server 在你亂猜猜錯(cuò)幾次之后就有可能把你 ban 掉不讓你繼續(xù)猜,所以沒什么問題。
不過這邊要特別注意的一點(diǎn)是 Session ID 基本上是種認(rèn)證不認(rèn)人的方式,也就是說一旦你的 Session ID 被偷走,別人就可以偽造你的身份來登錄了。而這個(gè) Session ID 通常都是保存在 Cookie 之中。
這就是為什么有些網(wǎng)站發(fā)生駭客入侵的情形之后你會突然被注銷,因?yàn)楹诳涂赡芡档揭慌?Session ID,這時(shí)候服務(wù)器就會把所有 Session 數(shù)據(jù)全部清空。
以故事來比喻就是把筆記本丟掉,買一本新的,這樣被偷走的那些 Session ID 就沒用了,而 Server 找不到你的 Session ID,自然就無法登入,因此把你給注銷了。
網(wǎng)站發(fā)生問題時(shí)客服會要你先把 Cookie 清掉也是類似的道理,因?yàn)?Cookie 跟狀態(tài)有關(guān),有時(shí)候可能程序有一些 Bug,把你導(dǎo)到了錯(cuò)誤的狀態(tài),把 Cookie 清空等于把狀態(tài)清空,重新再開始,就有可能變得正常。
總結(jié)
其實(shí)我原本以為我很懂 Cookie 跟 Session,但越研究越發(fā)現(xiàn)好像不是這么一回事,只是我自我感覺良好而已。
但把該看的數(shù)據(jù)都看完一遍之后,再讓自己沉淀個(gè)幾天,大致上就能完全理解整個(gè)脈絡(luò)的發(fā)展。
Session 是什么?就是一種讓 Request 變成 Stateful 的機(jī)制。以小明的例子來說,Session 就是一種讓客人之間能互相關(guān)聯(lián)起來的機(jī)制。
在故事里面我們用了紙條跟手機(jī)里的信息來比喻,有多種方式可以達(dá)成 Session。
在網(wǎng)絡(luò)世界中,也有很多種方式可以來實(shí)作 Session,前面介紹過第一種是地址欄,第二種就是靠 Cookie,而 Cookie 就是存在瀏覽器里的一些信息。
常見的錯(cuò)誤認(rèn)知是一定要有 Cookie 才能實(shí)作 Session,這是錯(cuò)誤的。
有了 Session 之后,會碰到數(shù)據(jù)被竄改的問題,這時(shí)候有兩種解決方式:
一個(gè)是 Cookie-based session,意思是你照舊把狀態(tài)存在 Cookie,但是加密以后再存。
另一個(gè)方法是把狀態(tài)存在 Server 端,靠一個(gè) Session ID 來辨識,這個(gè)狀態(tài)你可以存成檔案,可以存在內(nèi)存里,也可以存在數(shù)據(jù)庫,只是實(shí)作方式的不同而已,但原理都是一樣的。
而這個(gè)狀態(tài)儲存的地方在口語上也會被稱之為「Session」,例如說:「幫我把 user id 存在 Session 里」,或者是「注銷記得把 Session 清空」之類的。
所以在實(shí)際用法中,我認(rèn)為 Session 之所以不好理解是因?yàn)樘嗟胤接玫酵粋€(gè)詞,但卻是在指代不同的東西(可是又很類似)。跟 API 有點(diǎn)像,太多地方都用到這個(gè)詞了。