cookie是什么
cookie簡單來說就是由服務器產(chǎn)生按咒,存儲在客戶端的一個text類型文本。
為什么需要cookie
web程序是使用HTTP協(xié)議傳輸?shù)模鳫TTP協(xié)議是無狀態(tài)的協(xié)議,對于事務處理沒有記憶能力。缺少狀態(tài)意味著如果后續(xù)處理需要前面的信息已旧,則它必須重傳,這樣可能導致每次連接傳送的數(shù)據(jù)量增大
cookie 是怎么工作的
首先必須明確一點召娜,存儲cookie是瀏覽器提供的功能运褪。cookie 其實是存儲在瀏覽器中的純文本,瀏覽器的安裝目錄下會專門有一個 cookie 文件夾來存放各個域下設(shè)置的cookie玖瘸。
當網(wǎng)頁要發(fā)http請求時秸讹,瀏覽器會先檢查是否有相應的cookie,有則自動添加在request header中的cookie字段中雅倒。這些是瀏覽器自動幫我們做的嗦枢,而且每一次http請求瀏覽器都會自動幫我們做。這個特點很重要屯断,因為這關(guān)系到“什么樣的數(shù)據(jù)適合存儲在cookie中”文虏。
存儲在cookie中的數(shù)據(jù),每次都會被瀏覽器自動放在http請求中殖演,如果這些數(shù)據(jù)并不是每個請求都需要發(fā)給服務端的數(shù)據(jù)氧秘,瀏覽器這設(shè)置自動處理無疑增加了網(wǎng)絡(luò)開銷;但如果這些數(shù)據(jù)是每個請求都需要發(fā)給服務端的數(shù)據(jù)(比如身份認證信息)趴久,瀏覽器這設(shè)置自動處理就大大免去了重復添加操作丸相。所以對于那設(shè)置“每次請求都要攜帶的信息(最典型的就是身份認證信息)”就特別適合放在cookie中,其他類型的數(shù)據(jù)就不適合了彼棍。
但在 localStorage 出現(xiàn)之前灭忠,cookie被濫用當做了存儲工具膳算。什么數(shù)據(jù)都放在cookie中,即使這些數(shù)據(jù)只在頁面中使用而不需要隨請求傳送到服務端弛作。當然cookie標準還是做了一些限制的:每個域名下的cookie 的大小最大為4KB涕蜂,每個域名下的cookie數(shù)量在50個左右(不同瀏覽器數(shù)量不同)。
cookie 的格式
例如你可以直接在百度的調(diào)試模式下映琳,在控制臺輸入document.cookie
打印出的是一個字符串机隙,因為cookie本身就是存儲在瀏覽器中的字符串,由鍵值對 key=value構(gòu)成萨西,鍵值對之間由一個分號和一個空格隔開有鹿。
cookie 的屬性選項
每個cookie都有一定的屬性,如什么時候失效谎脯,要發(fā)送到哪個域名葱跋,哪個路徑等等。這些屬性是通過cookie選項來設(shè)置的源梭,cookie選項包括:expires娱俺、domain、path咸产、secure、HttpOnly仲闽。在設(shè)置任一個cookie時都可以設(shè)置相關(guān)的這些屬性脑溢,當然也可以不設(shè)置,這時會使用這些屬性的默認值赖欣。在設(shè)置這些屬性時屑彻,屬性之間由一個分號和一個空格隔開。代碼示例如下:
"key=name; expires=Thu, 25 Feb 2016 04:18:00 GMT; domain=ppsc.sankuai.com; path=/; secure; HttpOnly"
- expires
expires選項用來設(shè)置“cookie 什么時間內(nèi)有效”顶吮。expires其實是cookie失效日期社牲,expires必須是 GMT 格式的時間(可以通過new Date().toGMTString()或者 new Date().toUTCString() 來獲得)。
如expires=Thu, 25 Feb 2016 04:18:00 GMT表示cookie講在2016年2月25日4:18分之后失效悴了,對于失效的cookie瀏覽器會清空搏恤。如果沒有設(shè)置該選項,則默認有效期為session湃交,即會話cookie熟空。這種cookie在瀏覽器關(guān)閉后就沒有了。
expires 是 http/1.0協(xié)議中的選項搞莺,在新的http/1.1協(xié)議中expires已經(jīng)由 max-age 選項代替息罗,兩者的作用都是限制cookie 的有效時間。expires的值是一個時間點(cookie失效時刻= expires)才沧,而max-age 的值是一個以秒為單位時間段(cookie失效時刻= 創(chuàng)建時刻+ max-age)迈喉。
另外绍刮,max-age 的默認值是 -1(即有效期為 session );若max-age有三種可能值:負數(shù)挨摸、0孩革、正數(shù)。負數(shù):有效期session油坝;0:刪除cookie嫉戚;正數(shù):有效期為創(chuàng)建時刻+ max-age
- domain 和 path
domain是域名,path是路徑澈圈,兩者加起來就構(gòu)成了 URL彬檀,domain和path一起來限制 cookie 能被哪些 URL 訪問。
一句話概括:某cookie的 domain為“baidu.com”, path為“/ ”瞬女,若請求的URL(URL 可以是js/html/img/css資源請求窍帝,但不包括 XHR 請求)的域名是“baidu.com”或其子域如“api.baidu.com”、“dev.api.baidu.com”诽偷,且 URL 的路徑是“/ ”或子路徑“/home”坤学、“/home/login”,則瀏覽器會將此 cookie 添加到該請求的 cookie 頭部中报慕。
所以domain和path2個選項共同決定了cookie何時被瀏覽器自動添加到請求頭部中發(fā)送出去深浮。如果沒有設(shè)置這兩個選項,則會使用默認值眠冈。domain的默認值為設(shè)置該cookie的網(wǎng)頁所在的域名飞苇,path默認值為設(shè)置該cookie的網(wǎng)頁所在的目錄。
特別說明1:
發(fā)生跨域xhr請求時蜗顽,即使請求URL的域名和路徑都滿足 cookie 的 domain 和 path布卡,默認情況下cookie也不會自動被添加到請求頭部中。若想知道原因請閱讀本文最后一節(jié))
特別說明2:
domain是可以設(shè)置為頁面本身的域名(本域)雇盖,或頁面本身域名的父域忿等,但不能是公共后綴 public suffix。舉例說明下:如果頁面域名為 www.baidu.com, domain可以設(shè)置為“www.baidu.com”崔挖,也可以設(shè)置為“baidu.com”贸街,但不能設(shè)置為“.com”或“com”。
- secure
secure選項用來設(shè)置cookie只在確保安全的請求中才會發(fā)送狸相。當請求是HTTPS或者其他安全協(xié)議時匾浪,包含 secure 選項的 cookie才能被發(fā)送至服務器。
默認情況下卷哩,cookie不會帶secure選項(即為空)蛋辈。所以默認情況下,不管是HTTPS協(xié)議還是HTTP協(xié)議的請求,cookie 都會被發(fā)送至服務端冷溶。但要注意一點渐白,secure選項只是限定了在安全情況下才可以傳輸給服務端,但并不代表你不能看到這個 cookie逞频。
下面我們設(shè)置一個 secure類型的 cookie:
document.cookie = "name=huang; secure";
這里有個坑需要注意下:
如果想在客戶端即網(wǎng)頁中通過 js 去設(shè)置secure類型的 cookie纯衍,必須保證網(wǎng)頁是https協(xié)議的。在http協(xié)議的網(wǎng)頁中是無法設(shè)置secure類型cookie的苗胀。
- httpOnly
這個選項用來設(shè)置cookie是否能通過 js 去訪問襟诸。默認情況下,cookie不會帶httpOnly選項(即為空)基协,所以默認情況下歌亲,客戶端是可以通過js代碼去訪問(包括讀取、修改澜驮、刪除等)這個cookie的陷揪。當cookie帶httpOnly選項時,客戶端則無法通過js代碼去訪問(包括讀取杂穷、修改悍缠、刪除等)這個cookie。
在客戶端是不能通過js代碼去設(shè)置一個httpOnly類型的cookie的耐量,這種類型的cookie只能通過服務端來設(shè)置飞蚓。
——httpOnly與安全
從上面介紹中,大家是否會有這樣的疑問:為什么我們要限制客戶端去訪問cookie廊蜒?其實這樣做是為了保障安全趴拧。
試想:如果任何 cookie 都能被客戶端通過document.cookie獲取會發(fā)生什么可怕的事情。當我們的網(wǎng)頁遭受了 XSS 攻擊劲藐,有一段惡意的script腳本插到了網(wǎng)頁中八堡。這段script腳本做的事情是:通過document.cookie讀取了用戶身份驗證相關(guān)的 cookie樟凄,并將這些 cookie 發(fā)送到了攻擊者的服務器聘芜。攻擊者輕而易舉就拿到了用戶身份驗證信息,于是就可以搖搖大擺地冒充此用戶訪問你的服務器了(因為攻擊者有合法的用戶身份驗證信息缝龄,所以會通過你服務器的驗證)汰现。
如何設(shè)置 cookie?
知道了cookie的格式叔壤,cookie的屬性選項瞎饲,接下來我們就可以設(shè)置cookie了。首先得明確一點:cookie既可以由服務端來設(shè)置炼绘,也可以由客戶端來設(shè)置嗅战。
- 服務端設(shè)置 cookie
不管你是請求一個資源文件(如 html/js/css/圖片),還是發(fā)送一個ajax請求,服務端都會返回response驮捍。而response header中有一項叫set-cookie疟呐,是服務端專門用來設(shè)置cookie的。如下圖所示东且,服務端返回的response header中有5個set-cookie字段启具,每個字段對應一個cookie(注意不能將多個cookie放在一個set-cookie字段中),set-cookie字段的值就是普通的字符串珊泳,每個cookie還設(shè)置了相關(guān)屬性選項鲁冯。
注意:
一個set-Cookie字段只能設(shè)置一個cookie,當你要想設(shè)置多個 cookie色查,需要添加同樣多的set-Cookie字段薯演。
服務端可以設(shè)置cookie 的所有選項:expires、domain综慎、path涣仿、secure、HttpOnly
- 客戶端設(shè)置 cookie
document.cookie = "name=Jonh; ";
document.cookie="age=12; expires=Thu, 26 Feb 2116 11:50:25 GMT; domain=sankuai.com; path=/";
注意:
客戶端可以設(shè)置cookie 的下列選項:expires示惊、domain好港、path、secure(有條件:只有在https協(xié)議的網(wǎng)頁中米罚,客戶端設(shè)置secure類型的 cookie 才能成功)钧汹,但無法設(shè)置HttpOnly選項。
用 js 如何設(shè)置多個 cookie
document.cookie = "name=Jonh";
document.cookie = "age=12";
document.cookie = "class=111";