今天看到一篇cookie的文章,寫的特別詳細,感謝 晚晴幽草軒 的分享,原文連接http://mp.weixin.qq.com/s/NXrH7R8y2Dqxs9Ekm0u33wjavascript
原文以下,記錄到此供之後查閱並但願好文章能被更多須要的人看到php
背景前端
在HTTP協議的定義中,採用了一種機制來記錄客戶端和服務器端交互的信息,這種機制被稱爲cookie,cookie規範定義了服務器和客戶端交互信息的格式、生存期、使用範圍、安全性。vue
在JavaScript中能夠經過 document.cookie 來讀取或設置這些信息。因爲 cookie 多用在客戶端和服務端之間進行通訊,因此除了JavaScript之外,服務端的語言(如PHP)也能夠存取 cookie。java
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 基礎知識
cookie 是有大小限制的,大多數瀏覽器支持最大爲 4096 字節的 Cookie(具體會有所差別,可使用這個好用的工具:http://browsercookielimits.squawky.net/ 進行測試);若是 cookie 字符串的長度超過最大限制,則該屬性將返回空字符串。
因爲 cookie 最終都是以文件形式存放在客戶端計算機中,因此查看和修改 cookie 都是很方便的,這就是爲何常說 cookie 不能存放重要信息的緣由。
每一個 cookie 的格式都是這樣的:cookieName = Vaue;名稱和值都必須是合法的標示符。
cookie 是存在 有效期的。在默認狀況下,一個 cookie 的生命週期就是在瀏覽器關閉的時候結束。若是想要 cookie 能在瀏覽器關掉以後還可使用,就必需要爲該 cookie 設置有效期,也就是 cookie 的失效日期。
alert(typeof document.cookie)結果是 string.
cookie 有域和路徑這個概念。域就是domain的概念,由於瀏覽器是個注意安全的環境,因此不一樣的域之間是不能互相訪問 cookie 的(固然能夠經過特殊設置的達到 cookie 跨域訪問)。路徑就是routing的概念,一個網頁所建立的 cookie 只能被與這個網頁在同一目錄或子目錄下得全部網頁訪問,而不能被其餘目錄下得網頁訪問(這句話有點繞,一會看個例子就好理解了)。
其實建立cookie的方式和定義變量的方式有些類似,都須要使用 cookie 名稱和 cookie 值。同個網站能夠建立多個 cookie ,而多個 cookie 能夠存放在同一個cookie 文件中。
cookie 存在兩種類型:①:你瀏覽的當前網站自己設置的 cookie ②來自在網頁上嵌入廣告或圖片等其餘域來源的 第三方 cookie (網站可經過使用這些 cookie 跟蹤你的使用信息)
cookie 有兩種清除方式:①:經過瀏覽器工具清除 cookie (有第三方的工具,瀏覽器自身也有這種功能) ②經過設置 cookie 的有效期來清除 cookie.注:刪除 cookie 有時可能致使某些網頁沒法正常運行。
瀏覽器能夠經過設置來接受和拒絕訪問 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行,堪稱精妙,讀取操做以下:
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
更爲詳盡的說法:
因爲HTTP協議是無狀態的協議,因此服務端須要記錄用戶的狀態時,就須要用某種機制來識具體的用戶,這個機制就是Session.典型的場景好比購物車,當你點擊下單按鈕時,因爲HTTP協議無狀態,因此並不知道是哪一個用戶操做的,因此服務端要爲特定的用戶建立了特定的Session,用用於標識這個用戶,而且跟蹤用戶,這樣才知道購物車裏面有幾本書。這個Session是保存在服務端的,有一個惟一標識。在服務端保存Session的方法不少,內存、數據庫、文件都有。集羣的時候也要考慮Session的轉移,在大型的網站,通常會有專門的Session服務器集羣,用來保存用戶會話,這個時候 Session 信息都是放在內存的,使用一些緩存服務好比Memcached之類的來放 Session。
思考一下服務端如何識別特定的客戶?這個時候Cookie就登場了。每次HTTP請求的時候,客戶端都會發送相應的Cookie信息到服務端。實際上大多數的應用都是用 Cookie 來實現Session跟蹤的,第一次建立Session的時候,服務端會在HTTP協議中告訴客戶端,須要在 Cookie 裏面記錄一個Session ID,之後每次請求把這個會話ID發送到服務器,我就知道你是誰了。有人問,若是客戶端的瀏覽器禁用了 Cookie 怎麼辦?通常這種狀況下,會使用一種叫作URL重寫的技術來進行會話跟蹤,即每次HTTP交互,URL後面都會被附加上一個諸如 sid=xxxxx 這樣的參數,服務端據此來識別用戶。
Cookie其實還能夠用在一些方便用戶的場景下,設想你某次登錄過一個網站,下次登陸的時候不想再次輸入帳號了,怎麼辦?這個信息能夠寫到Cookie裏面,訪問網站的時候,網站頁面的腳本能夠讀取這個信息,就自動幫你把用戶名給填了,可以方便一下用戶。這也是Cookie名稱的由來,給用戶的一點甜頭。
因此,總結一下:
Session是在服務端保存的一個數據結構,用來跟蹤用戶的狀態,這個數據能夠保存在集羣、數據庫、文件中;
Cookie是客戶端保存用戶信息的一種機制,用來記錄用戶的一些信息,也是實現Session的一種方式。
Cookie與Session問答
Cookie運行在客戶端,Session運行在服務端,對嗎?
A:不徹底正確。Cookie是運行在客戶端,有客戶端進行管理;Session雖然是運行在服務器端,可是sessionID做爲一個Cookie是存儲在客戶端的。
瀏覽器禁止Cookie,Cookie就不能用了,但Session不會受瀏覽器影響,對嗎?
A:錯。瀏覽器禁止Cookie,Cookie確實不能用了,Session會受瀏覽器端的影響。很簡單的實驗,在登陸一個網站後,清空瀏覽器的Cookie和隱私數據,單機後臺的鏈接,就會由於丟失Cookie而退出。固然,有辦法經過URL傳遞Session。
瀏覽器關閉後,Cookie和Session都消失了,對嗎?
A:錯。存儲在內存中額Cookie確實會隨着瀏覽器的關閉而消失,但存儲在硬盤上的不會。更頑固的是Flash Cookie,不過如今不少系統優化軟件和新版瀏覽器都已經支持刪除Flash Cookie。百度採用了這樣的技術記憶用戶:Session在瀏覽器關閉後也不會消失,除非正常退出,代碼中使用了顯示的unset刪除Session。不然Session可能被回收,也有可能永遠殘留在系統中。
Session 比 Cookie 更安全嗎? 不該該大量使用Cookie嗎?
A:錯誤。Cookie確實可能存在一些不安全因素,但和JavaScript同樣,即便突破前端驗證,還有後端保障安全。一切都還要看設計,尤爲是涉及提權的時候,特別須要注意。一般狀況下,Cookie和Session是綁定的,得到Cookie就至關於得到了Session,客戶端把劫持的Cookie原封不動地傳給服務器,服務器收到後,原封不動地驗證Session,若Session存在,就實現了Cookie和Session的綁定過程。所以,不存在Session比Cookie更安全這種說法。若是說不安全,也是因爲代碼不安全,錯誤地把用做身份驗證的Cookie做爲權限驗證來使用。
Session是建立在服務器上的,應該少用Session而多用Cookie,對嗎?
A:錯。Cookie能夠提升用戶體驗,但會加大網絡之間的數據傳輸量,應儘可能在Cookie中僅保存必要的數據。
若是把別人機器上的Cookie文件複製到個人電腦上(假設使用相同的瀏覽器),是否是可以登陸別人的賬號呢?如何防範?
A:是的。這屬於Cookie劫持的一種作法。要避免這種狀況,須要在Cookie中針對IP、UA等加上特殊的校驗信息,而後和服務器端進行比對。
在IE瀏覽器下登陸某網站,換成Firefox瀏覽器是否仍然是未登陸狀態?使用IE登陸了騰訊網站後,爲何使用Firefox能保持登陸狀態?
A:不一樣瀏覽器使用不一樣的Cookie管理機制,沒法實現公用Cookie。若是使用IE登陸騰訊網站,使用Firefox也能登陸,這是因爲在安裝騰訊QQ軟件時,你的電腦上同時安裝了針對這兩個瀏覽器的插件,能夠識別本地已登陸QQ號碼進而自動登陸。本質上,不屬於共用Cookie的範疇。