天天看點

Cookie與Session的差別詳解

轉發自http://www.jeffjade.com/2016/10/31/115-summary-of-cookie/

Cookie與Session的差別詳解

晚晴幽草軒

背景

  在HTTP協定的定義中,采用了一種機制來記錄用戶端和伺服器端互動的資訊,這種機制被稱為cookie,cookie規範定義了伺服器和用戶端互動資訊的格式、生存期、使用範圍、安全性。

  在JavaScript中可以通過 document.cookie 來讀取或設定這些資訊。由于 cookie 多用在用戶端和服務端之間進行通信,是以除了JavaScript以外,服務端的語言(如PHP)也可以存取 cookie。

Cookie詳解

  Cookie在遠端浏覽器端存儲資料并以此跟蹤和識别使用者的機制。從實作上說,Cookie是存儲在用戶端上的一小段資料,浏覽器(即用戶端)通過HTTP協定和伺服器端進行Cookie互動。

  Cooke獨立于語言存在,嚴格地說,Cookie并不是由PHP、Java等語言實作的,而是由這些語言對Cookie進行間接操作,即發送HTTP指令,浏覽器收到指令便操作Cookie并傳回給伺服器。是以,Cookie是由浏覽器實作和管理的。舉例說,PHP并沒有真正設定過Cookie,隻是發出指令讓浏覽器來做這件事。PHP中可以使用setcookie() 或 setrawcookie() 函數設定Cookie。setcookie()最後一個參數HttpOnly設定了後,JavaScript就無法讀取到這個Cookie。

  設定Cookie時需注意:①函數有傳回值,false失敗,true成功,成功僅供參考,不代表用戶端一定能接收到;②PHP設定的Cookie不能立即生效,要等下一個頁面才能看到(Cookie從伺服器傳給浏覽器,下個頁面浏覽器才能把設定的Cookie傳回給伺服器);如果是JavaScript設定的,是立即生效的;③Cookie沒有顯示的删除函數,可以設定expire過期時間,自動觸發浏覽器的删除機制。

  Cookie是HTTP頭的一部分,即現發送或請求Cookie,才是data域;setcookie()等函數必須在資料之前調用,這和header() 函數是相同的。不過也可以使用輸出緩沖函數延遲腳本的輸出,知道設定好所有Cookie和其他HTTP标頭。

  Cookie通常用來存儲一些不是很敏感的資訊,或者進行登入控制,也可用來記住使用者名、記住免密碼登入、防止刷票等。每個域名下允許的Cookie是有限制的,根據浏覽器這個限制也不同。Cookie不是越多越好,它會增加寬帶,增加流量消耗,是以不要濫用Cookie;不要把Cookie當作用戶端的存儲器來用。一個域名的每個Cookie限制以4千位元組(KB)鍵值對的形式存儲。

  還有一種Cookie是Flash建立的,成為Flash Shard Object,又稱Flash Cookie,即使清空浏覽器所有隐私資料,這類頑固的Cookie還會存在硬碟上,因為它隻受Flash管理,很多網站采用這種技術識别使用者。

  Cookie跨域,主要是為了統一應用平台,實作單點登入;需使用P3P協定(Platform for Privacy Preferences),通過P3P使使用者自己可以指定浏覽器的隐私政策,達到存儲第三方Cookie的目的,隻需要在響應使用者請求時,在HTTP的頭資訊中增加關于P3P的配置資訊就可以了。Cookie跨域涉及兩個不同的應用,習慣上稱為第一方和第三方。第三方通常是來自别人的廣告、或Iframe别的網站的URL,這些第三方網站可能使用的Cookie。

Cookie格式

Cookie中儲存的資訊都是文本資訊,在用戶端和伺服器端互動過程中,cookie資訊被附加在HTTP消息頭中傳遞,cookie的資訊由鍵/值對組成。下面是一個HTTP頭中cookie的例子:

Set-Cookie: key = value; Path=/

Cookie中存放的資訊包含cookie本身屬性和使用者自定義屬性,一個cookie隻能包含一個自定義鍵/值對。Cookie本身屬性有”Comment” 、”Domain”、”Max-Age”、”Path”、”Secure”、”Version”。

Comment 屬性是cookie的産生着對該cookie的描述;

Domain 屬性定義可通路該cookie的域名,對一些大的網站,如果希望cookie可以在子網站中共享,可以使用該屬性。例如設定Domain為 .bigsite.com ,則sub1.bigsite.com和sub2.bigsite.com都可以通路已儲存在用戶端的cookie,這時還需要将Path設定為/。

Max-Age 屬性定義cookie的有效時間,用秒計數,當超過有效期後,cookie的資訊不會從用戶端附加在HTTP消息頭中發送到服務端。

Path 屬性定義網站上可以通路cookie的頁面的路徑,預設狀态下Path為産生cookie時的路徑,此時cookie可以被該路徑以及其子路徑下的頁面通路;可以将Path設定為/,使cookie可以被網站下所有頁面通路。

Secure 屬性值定義cookie的安全性,當該值為true時必須是HTTPS狀态下cookie才從用戶端附加在HTTP消息中發送到服務端,在HTTP時cookie是不發送的;Secure為false時則可在HTTP狀态下傳遞cookie,Secure預設為false。

Version 屬性定義cookie的版本,由cookie的建立者定義。

Cookie的建立

  Cookie可以在伺服器端建立,然後cookie資訊附加在HTTP消息頭中傳到用戶端,如果cookie定義了有效期,則本儲存在用戶端本地磁盤。儲存cookie的檔案是一個文本檔案,是以不用擔心此檔案中的内容會被執行而破壞客戶的機器。支援Web端開發的語言都有建立cookie的方法或函數,以及設定cookie屬性和添加自定義屬性的方法或函數,最後是将cookie附加到傳回用戶端的HTTP消息頭中。

  建立cookie時如果不指定生存有效時間,則cookie隻在浏覽器關閉前有效,cookie會在伺服器端和用戶端傳輸,但是不會儲存在客戶機的磁盤上,打開新的浏覽器将不能獲得原先建立的cookie資訊。

  Cookie資訊儲存在本地時會儲存到目前登入使用者專門目錄下,儲存的cookie檔案名中會包含建立cookie所在頁面網站的域名,當浏覽器再次連接配接該網站時,會從本機cookie存放目錄下選出該網站的有效cookie,将儲存在其中的資訊附加在HTTP消息頭中發送到伺服器端,伺服器端程式就可根據上次儲存在cookie的資訊為通路客戶提供“記憶”或個性化服務。

  Cookie除了可以在伺服器端建立外,也可以在用戶端的浏覽器中用用戶端腳本(如javascript)建立。用戶端建立的cookie的性質和伺服器端建立的cookie一樣,可以儲存在本地,也可以被傳送到伺服器端被伺服器程式讀取。   

Cookie 基礎知識

  1. cookie 是有大小限制的,大多數浏覽器支援最大為 4096 位元組的 Cookie(具體會有所差異,可以使用這個好用的工具:http://browsercookielimits.squawky.net/ 進行測試);如果 cookie 字元串的長度超過最大限制,則該屬性将傳回空字元串。
  2. 由于 cookie 最終都是以檔案形式存放在用戶端計算機中,是以檢視和修改 cookie 都是很友善的,這就是為什麼常說 cookie 不能存放重要資訊的原因。
  3. 每個 cookie 的格式都是這樣的:=<值>;名稱和值都必須是合法的标示符。
  4. cookie 是存在 有效期的。在預設情況下,一個 cookie 的生命周期就是在浏覽器關閉的時候結束。如果想要 cookie 能在浏覽器關掉之後還可以使用,就必須要為該 cookie 設定有效期,也就是 cookie 的失效日期。
  5. alert(typeof document.cookie)結果是 string.
  6. cookie 有域和路徑這個概念。域就是domain的概念,因為浏覽器是個注意安全的環境,是以不同的域之間是不能互相通路 cookie 的(當然可以通過特殊設定的達到 cookie 跨域通路)。路徑就是routing的概念,一個網頁所建立的 cookie 隻能被與這個網頁在同一目錄或子目錄下得所有網頁通路,而不能被其他目錄下得網頁通路(這句話有點繞,一會看個例子就好了解了)。
  7. 其實建立cookie的方式和定義變量的方式有些相似,都需要使用 cookie 名稱和 cookie 值。同個網站可以建立多個 cookie ,而多個 cookie 可以存放在同一個cookie 檔案中。   
  8. cookie 存在兩種類型:①:你浏覽的目前網站本身設定的 cookie ②來自在網頁上嵌入廣告或圖檔等其他域來源的 第三方 cookie (網站可通過使用這些 cookie 跟蹤你的使用資訊)
  9. cookie 有兩種清除方式:①:通過浏覽器工具清除 cookie (有第三方的工具,浏覽器自身也有這種功能) ②通過設定 cookie 的有效期來清除 cookie. 注:删除 cookie 有時可能導緻某些網頁無法正常運作。
  10. 浏覽器可以通過設定來接受和拒絕通路 cookie。出于功能和性能的原因考慮,建議盡量降低 cookie 的使用數量,并且要盡量使用小 cookie。

Cookie的使用

  從cookie的定義可以看到,cookie一般用于采用HTTP作為進行資訊交換協定的用戶端和伺服器端用于記錄需要持久化的資訊。一般是由伺服器端建立要記錄的資訊,然後傳遞到用戶端,由用戶端從HTTP消息中取出資訊,儲存在本機磁盤上。當用戶端再次通路伺服器端時,從本機磁盤上讀出原來儲存的資訊,附加到HTTP消息中發送給伺服器端,伺服器端從HTTP消息中讀取資訊,根據實際應用的需求進行進一步的處理。

  伺服器端cookie的建立和再次讀取功能通常由伺服器端程式設計語言實作,用戶端cookie的儲存、讀取一般由浏覽器來提供,并且對cookie的安全性方面可以進行設定,如是否可以在本機儲存cookie。

  由于cookie資訊以明文方式儲存在文本檔案中,對一些敏感資訊如密碼、銀行帳号如果要儲存在本地cookie檔案中,最好采用加密形式。

  

 與cookie類似的另一個概念是會話(Session),會話一般是記錄用戶端和伺服器端從用戶端浏覽器連接配接上伺服器端到關閉浏覽器期間的持久資訊。會話一般儲存在記憶體中,不儲存到磁盤上。會話可以通過cookie機制來實作,對于不支援cookie的用戶端,會話可以采用URL重寫方式來實作。可以将會話了解為記憶體中的cookie。

  使用會話會對系統伸縮性造成負面影響,當伺服器端要在很多台伺服器上同步複制會話對象時,系統性能會受到較大傷害,尤其會話對象較大時。這種情況下可以采用cookie,将需要記錄的資訊儲存在用戶端,每次請求時發送到伺服器端,伺服器端不保留狀态資訊,避免在伺服器端多台機器上複制會話而造成的性能下降。   

Cookie 基本操作

對于 Cookie 得常用操作有,存取,讀取,以及設定有效期;具體可以參照 JavaScript 操作 Cookie 一文;但,近期在前端編碼方面,皆以Vue為沖鋒利器,是以就有用到一款插件 vue-cookie,其代碼僅30行,堪稱精妙,讀取操作如下:

1
     
     
      2
     
     
      3
     
     
      4
     
     
      5
     
     
      6
     
     
      7
     
     
      8
     
     
      9
     
     
      10
     
     
      11
     
     
      12
     
     
      13
     
     
      14
           
set: function (name, value, days) {
     
     
          var d = new Date;
     
     
          d.setTime(d.getTime() + 24*60*60*1000*days);
     
     
          window.document.cookie = name + "=" + value + ";path=/;expires=" + d.toGMTString();
     
     
      },
     
     
      get: function (name) {
     
     
          var v = window.document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)');
     
     
          return v ? v[2] : null;
     
     
      },
     
     
      delete: function (name) {
     
     
          this.set(name, '', -1);
     
     
      }
           

cookie 域概念

路徑能解決在同一個域下通路 cookie 的問題,咱們接着說 cookie 實作同域之間通路的問題。文法如下:

document.cookie = “name=value;path=path;domain=domain“

紅色的domain就是設定的 cookie 域的值。例如 “www.qq.com” 與 “sports.qq.com” 公用一個關聯的域名”qq.com”,我們如果想讓”sports.qq.com” 下的cookie被 “www.qq.com” 通路,我們就需要用到cookie 的domain屬性,并且需要把path屬性設定為 “/“。例:

document.cookie = “username=Darren;path=/;domain=qq.com“

注:一定的是同域之間的通路,不能把domain的值設定成非主域的域名。

cookie 安全性

通常 cookie 資訊都是使用HTTP連接配接傳遞資料,這種傳遞方式很容易被檢視,在控制台下運作

document.cookie

,一目了然;是以 cookie 存儲的資訊容易被竊取。假如 cookie 中所傳遞的内容比較重要,那麼就要求使用加密的資料傳輸。是以 cookie 的這個屬性的名稱是“secure”,預設的值為空。如果一個 cookie 的屬性為secure,那麼它與伺服器之間就通過HTTPS或者其它安全協定傳遞資料。文法如下:

document.cookie = “username=Darren;secure”

把cookie設定為secure,隻保證 cookie 與伺服器之間的資料傳輸過程加密,而儲存在本地的 cookie檔案并不加密。如果想讓本地cookie也加密,得自己加密資料。

注: 就算設定了secure 屬性也并不代表他人不能看到你機器本地儲存的 cookie 資訊,是以說到底,别把重要資訊放cookie就對了。

Session詳解

  Session即回話,指一種持續性的、雙向的連接配接。Session與Cookie在本質上沒有差別,都是針對HTTP協定的局限性而提出的一種保持用戶端和伺服器間保持會話連接配接狀态的機制。Session也是一個通用的标準,但在不同的語言中實作有所不同。針對Web網站來說,Session指使用者在浏覽某個網站時,從進入網站到浏覽器關閉這段時間内的會話。由此可知,Session實際上是一個特定的時間概念。

  使用Session可以在網站的上下文不同頁面間傳遞變量、使用者身份認證、程式狀态記錄等。常見的形式就是配合Cookie使用,實作儲存使用者登入狀态功能。和Cookie一樣,session_start() 必須在程式最開始執行,前面不能有任何輸出内容,否則會出現警告。PHP的Session預設通過檔案的方式實作,即存儲在伺服器端的Session檔案,每個Session一個檔案。

  Session通過一個稱為PHPSESSID的Cookie和伺服器聯系。Session是通過sessionID判斷用戶端使用者的,即Session檔案的檔案名。sessionID實際上是在用戶端和服務端之間通過HTTP Request 和 HTTP Response傳來傳去。sessionID按照一定的算法生成,必須包含在 HTTP Request 裡面,保證唯一性和随機性,以確定Session的安全。如果沒有設定 Session 的生成周期, sessionID存儲在記憶體中,關閉浏覽器後該ID自動登出;重新請求該頁面,會重新注冊一個sessionID。如果用戶端沒有禁用Cookie,Cookie在啟動Session回話的時候扮演的是存儲sessionID 和 Session 生存期的角色。Session過期後,PHP會對其進行回收。

  假設用戶端禁用Cookie,可以通過URL或者隐藏表單傳遞sessionID;php.ini中把session.use_trans_sid 設成1,那麼連接配接後就會自己加Session的ID。

  Session以檔案的形式存放在本地硬碟的一個目錄中,當比較多時,磁盤讀取檔案就會比較慢,是以把Session分目錄存放。

  對于通路量大的站點,用預設的Session存儲方式并不适合,較優的方法是用Data Base存取Session。在大流量的網站中,Session入庫存在效率不高、占據資料庫connection資源等問題。針對這種情況,可以使用Memcached、Redis等Key-Value資料存儲方案實作高并發、大流量的Session存儲。

session與cookie的差別:

1,session 在伺服器端,cookie 在用戶端(浏覽器)

2,session 存在在伺服器的一個檔案裡(預設),不是記憶體

3,session 的運作依賴 session id,而 session id 是存在 cookie 中的,也就是說,如果 浏覽器禁用了 cookie ,同時 session 也會失效(當然也可以在 url 中傳遞)

4,session 可以放在 檔案,資料庫,或記憶體中都可以。

5,使用者驗證這種場合一般會用 session

是以,維持一個會話的核心就是用戶端的唯一辨別,即 session id

更為詳盡的說法:

  1. 由于HTTP協定是無狀态的協定,是以服務端需要記錄使用者的狀态時,就需要用某種機制來識具體的使用者,這個機制就是Session.典型的場景比如購物車,當你點選下單按鈕時,由于HTTP協定無狀态,是以并不知道是哪個使用者操作的,是以服務端要為特定的使用者建立了特定的Session,用用于辨別這個使用者,并且跟蹤使用者,這樣才知道購物車裡面有幾本書。這個Session是儲存在服務端的,有一個唯一辨別。在服務端儲存Session的方法很多,記憶體、資料庫、檔案都有。叢集的時候也要考慮Session的轉移,在大型的網站,一般會有專門的Session伺服器叢集,用來儲存使用者會話,這個時候 Session 資訊都是放在記憶體的,使用一些緩存服務比如Memcached之類的來放 Session。
  2. 思考一下服務端如何識别特定的客戶?這個時候Cookie就登場了。每次HTTP請求的時候,用戶端都會發送相應的Cookie資訊到服務端。實際上大多數的應用都是用 Cookie 來實作Session跟蹤的,第一次建立Session的時候,服務端會在HTTP協定中告訴用戶端,需要在 Cookie 裡面記錄一個Session ID,以後每次請求把這個會話ID發送到伺服器,我就知道你是誰了。有人問,如果用戶端的浏覽器禁用了 Cookie 怎麼辦?一般這種情況下,會使用一種叫做URL重寫的技術來進行會話跟蹤,即每次HTTP互動,URL後面都會被附加上一個諸如 sid=xxxxx 這樣的參數,服務端據此來識别使用者。
  3. Cookie其實還可以用在一些友善使用者的場景下,設想你某次登陸過一個網站,下次登入的時候不想再次輸入賬号了,怎麼辦?這個資訊可以寫到Cookie裡面,通路網站的時候,網站頁面的腳本可以讀取這個資訊,就自動幫你把使用者名給填了,能夠友善一下使用者。這也是Cookie名稱的由來,給使用者的一點甜頭。

    是以,總結一下:

    Session是在服務端儲存的一個資料結構,用來跟蹤使用者的狀态,這個資料可以儲存在叢集、資料庫、檔案中;

    Cookie是用戶端儲存使用者資訊的一種機制,用來記錄使用者的一些資訊,也是實作Session的一種方式。

Cookie與Session問答

  1. Cookie運作在用戶端,Session運作在服務端,對嗎?

    A:不完全正确。Cookie是運作在用戶端,有用戶端進行管理;Session雖然是運作在伺服器端,但是sessionID作為一個Cookie是存儲在用戶端的。

  2. 浏覽器禁止Cookie,Cookie就不能用了,但Session不會受浏覽器影響,對嗎?

    A:錯。浏覽器禁止Cookie,Cookie确實不能用了,Session會受浏覽器端的影響。很簡單的實驗,在登入一個網站後,清空浏覽器的Cookie和隐私資料,單機背景的連接配接,就會因為丢失Cookie而退出。當然,有辦法通過URL傳遞Session。

  3. 浏覽器關閉後,Cookie和Session都消失了,對嗎?

    A:錯。存儲在記憶體中額Cookie确實會随着浏覽器的關閉而消失,但存儲在硬碟上的不會。更頑固的是Flash Cookie,不過現在很多系統優化軟體和新版浏覽器都已經支援删除Flash Cookie。百度采用了這樣的技術記憶使用者:Session在浏覽器關閉後也不會消失,除非正常退出,代碼中使用了顯示的unset删除Session。否則Session可能被回收,也有可能永遠殘留在系統中。

  4. Session 比 Cookie 更安全嗎? 不應該大量使用Cookie嗎?

    A:錯誤。Cookie确實可能存在一些不安全因素,但和JavaScript一樣,即使突破前端驗證,還有後端保障安全。一切都還要看設計,尤其是涉及提權的時候,特别需要注意。通常情況下,Cookie和Session是綁定的,獲得Cookie就相當于獲得了Session,用戶端把劫持的Cookie原封不動地傳給伺服器,伺服器收到後,原封不動地驗證Session,若Session存在,就實作了Cookie和Session的綁定過程。是以,不存在Session比Cookie更安全這種說法。如果說不安全,也是由于代碼不安全,錯誤地把用作身份驗證的Cookie作為權限驗證來使用。

  5. Session是建立在伺服器上的,應該少用Session而多用Cookie,對嗎?

    A:錯。Cookie可以提高使用者體驗,但會加大網絡之間的資料傳輸量,應盡量在Cookie中僅儲存必要的資料。

  6. 如果把别人機器上的Cookie檔案複制到我的電腦上(假設使用相同的浏覽器),是不是能夠登入别人的帳号呢?如何防範?

      A:是的。這屬于Cookie劫持的一種做法。要避免這種情況,需要在Cookie中針對IP、UA等加上特殊的校驗資訊,然後和伺服器端進行比對。

  7. 在IE浏覽器下登入某網站,換成Firefox浏覽器是否仍然是未登入狀态?使用IE登入了騰訊網站後,為什麼使用Firefox能保持登入狀态?

      A:不同浏覽器使用不同的Cookie管理機制,無法實作公用Cookie。如果使用IE登入騰訊網站,使用Firefox也能登入,這是由于在安裝騰訊QQ軟體時,你的電腦上同時安裝了針對這兩個浏覽器的插件,可以識别本地已登入QQ号碼進而自動登入。本質上,不屬于共用Cookie的範疇。

繼續閱讀