在初級面試中,關于Cookie和Session的區別是一個高頻的面試題。如果只是機械的回答一下它們的區別,那你可能真的不了解Cookie和Session,就更別說靈活運用了。
這篇文章帶你從Cookie和Session的初級應用到高級應用捋一遍,看看有多少不知道的內容。
什么是Cookie?
我們知道HTTP協議是無狀態的,一次請求完成,不會持久化請求與相應的信息。那么,在購物車、用戶登錄狀態、頁面個性化設置等場景下,就無法識別特定用戶的信息。這時Cookie就出現了。
Cookie是客戶端保存用戶信息的一種機制,將服務器發送到瀏覽器的數據保存在本地,下次向同一服務器再發起請求時被攜帶發送。對于Cookie,可以設置過期時間。
通常,Cookie用于告知服務端兩個請求是否來自同一瀏覽器,如保持用戶的登錄狀態。這樣就解決了HTTP無狀態的問題。
Cookie主要用于以下方面:
- 會話狀態管理(如用戶登錄狀態、購物車、游戲分數或其它需要記錄的信息)
- 個性化設置(如用戶自定義設置、主題等)
- 瀏覽器行為跟蹤(如跟蹤分析用戶行為等)
Cookie存儲在客戶端,這就意味著,可以通過一些方式進行修改,欺騙服務器。針對這個問題,怎么解決呢?那就引入了Session。
什么是Session?
Session代表服務器和客戶端一次會話的過程。
維基百科這樣解釋道:在計算機科學領域來說,尤其是在網絡領域,會話(session)是一種持久網絡協議,在用戶(或用戶代理)端和服務器端之間創建關聯,從而起到交換數據包的作用機制,session在網絡協議(例如telnet或FTP)中是非常重要的部分。
對照Cookie,Session是一種在服務器端保存數據的機制,用來跟蹤用戶狀態的數據結構,可以保存在文件、數據庫或者集群中。
當在應用程序的Web頁之間跳轉時,存儲在Session對象中的變量將不會丟失,而會在整個用戶會話中一直存在下去。當客戶端關閉會話,或者Session超時失效時會話結束。
目前大多數的應用都是用Cookie實現Session跟蹤的。第一次創建Session時,服務端會通過在HTTP協議中返回給客戶端,在Cookie中記錄SessionID,后續請求時傳遞SessionID給服務,以便后續每次請求時都可分辨你是誰。
Cookie與Session的區別
關于Cookie與Session的區別,就是在面試中經常回答的問題了。
- 作用范圍不同,Cookie 保存在客戶端(瀏覽器),Session 保存在服務器端。
- 存取方式的不同,Cookie只能保存 ASCII,Session可以存任意數據類型,比如UserId等。
- 有效期不同,Cookie可設置為長時間保持,比如默認登錄功能功能,Session一般有效時間較短,客戶端關閉或者Session超時都會失效。
- 隱私策略不同,Cookie存儲在客戶端,信息容易被竊取;Session存儲在服務端,相對安全一些。
- 存儲大小不同, 單個Cookie 保存的數據不能超過 4K,Session可存儲數據遠高于Cookie。
禁用Cookie會怎樣?
如果客戶在瀏覽器禁用了Cookie,該怎么辦呢?
方案一:拼接SessionId參數。在GET或POST請求中拼接SessionID,GET請求通常通過URL后面拼接參數來實現,POST請求可以放在Body中。無論哪種形式都需要與服務器獲取保持一致。
這種方案比較常見,比如老外的網站,經常會提示是否開啟Cookie。如果未點同意或授權,會發現瀏覽器的URL路徑中往往有@quot;?sessionId=123abc@quot;這樣的參數。
方案二:基于Token(令牌)。在APP應用中經常會用到Token來與服務器進行交互。Token本質上就是一個唯一的字符串,登錄成功后由服務器返回,標識客戶的臨時授權,客戶端對其進行存儲,在后續請求時,通常會將其放在HTTP的Header中傳遞給服務器,用于服務器驗證請求用戶的身份。
分布式系統中Session如何處理?
在分布式系統中,往往會有多臺服務器來處理同一業務。如果用戶在A服務器登錄,Session位于A服務器,那么當下次請求被分配到B服務器,將會出現登錄失效的問題。
針對類似的場景,有三種解決方案:
方案一:請求精確定位。也就是通過負載均衡器讓來自同一IP的用戶請求始終分配到同一服務上。比如,Nginx的ip_hash策略,就可以做到。
方案二:Session復制共享。該方案的目標就是確保所有的服務器的Session是一致的。像Tomcat等多數主流web服務器都采用了Session復制實現Session的共享.
方案三:基于共享緩存。該方案是通過將Session放在一個公共地方,各個服務器使用時去取即可。比如,存放在Redis、Memcached等緩存中間件中。
在Spring Boot項目中,如果集成了Redis,Session共享可以非常方便的實現。
同源策略與跨域請求
所謂的“同源”指的是“三個相同”:協議相同、域名相同、端口相同。只有這三個完全相同,才算是同源。
同源策略的目的:是為了保證用戶信息的安全,防止惡意的網站竊取數據。
比如,用戶訪問了銀行網站A,再去瀏覽其他網站,如果其他網站可以讀取A的Cookie,隱私信息便會泄露。更可怕的是,通常Cookie還用來保存用戶登錄狀態,會出現冒充用戶行為。因此,@quot;同源策略@quot;是必需的,如果Cookie可以共享,互聯網就毫無安全可言了。
同源策略保證了一定的安全性,但在某些場景下也帶來了不便,比如常見的跨域請求問題。
在HTML中,@lt;a@gt;,@lt;form@gt;, @lt;img@gt;, @lt;script@gt;, @lt;iframe@gt;, @lt;link@gt; 等標簽以及Ajax都可以指向一個資源地址,而所謂的跨域請求就是指:當前發起請求的域與該請求指向的資源所在的域不一樣。同源即同域,三項有一項不同便會出現跨域請求。
瀏覽器會對跨域請求做出限制,因為跨域請求可能會被利用發動CSRF攻擊。
CSRF(Cross-site request forgery),即“跨站請求偽造”,也被稱為:one click attack/session riding,縮寫為:CSRF/XSRF。CSRF攻擊者在用戶已經登錄目標網站之后,誘使用戶訪問一個攻擊頁面,利用目標網站對用戶的信任,以用戶身份在攻擊頁面對目標網站發起偽造用戶操作的請求,達到攻擊目的。
針對跨域請求通常有如下方法:
- 通過代理避開跨域請求;
- 通過Jsonp跨域;
- 通過跨域資源共享(CORS);
關于跨域的具體解決步驟,就不再展開了。
小結
在準備面試題時,我們通常只會去背誦Cookie和Session的區別。但只有系統的學習才能更深刻的把知識點串聯起來,形成強大記憶,融會貫通的效果。比如,本文了解了Cookie與Session出現的原因、解決的問題以及引入之后又會帶來什么問題等,更加系統全面的掌握了這一知識點。
原文鏈接:https://mp.weixin.qq.com/s/cuTmhjnzdngE0EEb5RlbxQ