1、 什么是cookie?
在進(jìn)行一個(gè)頁面url解析時(shí),常常發(fā)現(xiàn)一些不存在于請(qǐng)求數(shù)據(jù)中的參數(shù),這些參數(shù)哪里來的?答案就是cookie。cookie一般保存在請(qǐng)求頭中以一個(gè)單獨(dú)的cookies字段保存

上圖就是一個(gè)典型的請(qǐng)求頭,包含一些基礎(chǔ)header信息如Accept-Encoding、User-Agent、Host、Content-Type等以及cookies。
2、 cookie的作用
首先必須明確一點(diǎn),存儲(chǔ)cookie是瀏覽器提供的功能。cookie 其實(shí)是存儲(chǔ)在瀏覽器中的純文本,瀏覽器的安裝目錄下會(huì)專門有一個(gè) cookie 文件夾來存放各個(gè)域下設(shè)置的cookie。
當(dāng)網(wǎng)頁要發(fā)http請(qǐng)求時(shí),瀏覽器會(huì)先檢查是否有相應(yīng)的cookie,有則自動(dòng)添加在request header中的cookie字段中。這些是瀏覽器自動(dòng)幫我們做的,而且每一次http請(qǐng)求瀏覽器都會(huì)自動(dòng)幫我們做。這個(gè)特點(diǎn)很重要,因?yàn)檫@關(guān)系到“什么樣的數(shù)據(jù)適合存儲(chǔ)在cookie中”。
存儲(chǔ)在cookie中的數(shù)據(jù),每次都會(huì)被瀏覽器自動(dòng)放在http請(qǐng)求中,如果這些數(shù)據(jù)并不是每個(gè)請(qǐng)求都需要發(fā)給服務(wù)端的數(shù)據(jù),瀏覽器這設(shè)置自動(dòng)處理無疑增加了網(wǎng)絡(luò)開銷;但如果這些數(shù)據(jù)是每個(gè)請(qǐng)求都需要發(fā)給服務(wù)端的數(shù)據(jù)(比如身份認(rèn)證信息),瀏覽器這設(shè)置自動(dòng)處理就大大免去了重復(fù)添加操作。所以對(duì)于那設(shè)置“每次請(qǐng)求都要攜帶的信息(最典型的就是身份認(rèn)證信息)”就特別適合放在cookie中,其他類型的數(shù)據(jù)就不適合了。
但在 localStorage 出現(xiàn)之前,cookie被濫用當(dāng)做了存儲(chǔ)工具。什么數(shù)據(jù)都放在cookie中,即使這些數(shù)據(jù)只在頁面中使用而不需要隨請(qǐng)求傳送到服務(wù)端。當(dāng)然cookie標(biāo)準(zhǔn)還是做了一些限制的:每個(gè)域名下的cookie 的大小最大為4KB,每個(gè)域名下的cookie數(shù)量最多為20個(gè)(但很多瀏覽器廠商在具體實(shí)現(xiàn)時(shí)支持大于20個(gè))。
3、 cookie的工作過程
cookie是我們?cè)O(shè)置好的,已我做的項(xiàng)目為例,cookie包含以下內(nèi)容:

在cookie中保存的內(nèi)容為了安全經(jīng)常需要進(jìn)行加密,因?yàn)檫@些涉及用戶的一些個(gè)人信息以及服務(wù)器的一些秘鑰規(guī)則,這些數(shù)據(jù)是在登錄時(shí)產(chǎn)生的,會(huì)一直保存,每次訪問登錄后頁面,瀏覽器都會(huì)將cookie中信息發(fā)送至后臺(tái)進(jìn)行用戶身份校驗(yàn),只有校驗(yàn)通過才能返回正確數(shù)據(jù),否則重定向至那些不需要進(jìn)行身份校驗(yàn)的頁面,比如登錄首頁。再比如某些網(wǎng)站下載資源需要進(jìn)行身份校驗(yàn),只有vip才能下載,那么在post請(qǐng)求時(shí),如果沒有正確的cookie數(shù)據(jù),就會(huì)返回拒絕反饋。
【cookie一般是由后臺(tái)產(chǎn)生在登錄等請(qǐng)求完成后返回保存在瀏覽器】--------》
【客戶端發(fā)送請(qǐng)求,瀏覽器將cookie協(xié)同構(gòu)建url發(fā)送給服務(wù)器】---------》服務(wù)器接收請(qǐng)求參數(shù),解析url,請(qǐng)求頭的cookie信息先進(jìn)行身份校驗(yàn),校驗(yàn)通過則處理請(qǐng)求數(shù)據(jù),返回?cái)?shù)據(jù);錯(cuò)誤則根據(jù)業(yè)務(wù)邏輯進(jìn)行處理。
4、 構(gòu)造cookie
在開發(fā)者工具的Console中使用JS document.cookie可以查看到上面圖片中的cookie在瀏覽器中保存格式如下:

以字符串形式鏈接key=value;各個(gè)選項(xiàng)值間以“”;“”分隔。
每個(gè)cookie都有一定的屬性,如什么時(shí)候失效,要發(fā)送到哪個(gè)域名,哪個(gè)路徑等等。這些屬性是通過cookie選項(xiàng)來設(shè)置的,cookie選項(xiàng)包括:expires、domain、path、secure、HttpOnly。在設(shè)置任一個(gè)cookie時(shí)都可以設(shè)置相關(guān)的這些屬性,當(dāng)然也可以不設(shè)置,這時(shí)會(huì)使用這些屬性的默認(rèn)值。在設(shè)置這些屬性時(shí),屬性之間由一個(gè)分號(hào)和一個(gè)空格隔開。代碼示例如下:

expires選項(xiàng)用來設(shè)置“cookie 什么時(shí)間內(nèi)有效”。expires其實(shí)是cookie失效日期,expires必須是 GMT 格式的時(shí)間(可以通過new Date().toGMTString()或者 new Date().toUTCString() 來獲得)。
domain是域名,path是路徑,兩者加起來就構(gòu)成了 URL,domain和path一起來限制 cookie 能被哪些 URL 訪問。
一句話概括:某cookie的 domain為“baidu.com”, path為“/ ”,若請(qǐng)求的URL(URL 可以是js/html/img/css資源請(qǐng)求,但不包括 XHR 請(qǐng)求)的域名是“baidu.com”或其子域如“api.baidu.com”、“dev.api.baidu.com”,且 URL 的路徑是“/ ”或子路徑“/home”、“/home/login”,則瀏覽器會(huì)將此 cookie 添加到該請(qǐng)求的 cookie 頭部中。
所以domain和path2個(gè)選項(xiàng)共同決定了cookie何時(shí)被瀏覽器自動(dòng)添加到請(qǐng)求頭部中發(fā)送出去。如果沒有設(shè)置這兩個(gè)選項(xiàng),則會(huì)使用默認(rèn)值。domain的默認(rèn)值為設(shè)置該cookie的網(wǎng)頁所在的域名,path默認(rèn)值為設(shè)置該cookie的網(wǎng)頁所在的目錄。
secure選項(xiàng)用來設(shè)置cookie只在確保安全的請(qǐng)求中才會(huì)發(fā)送。當(dāng)請(qǐng)求是HTTPS或者其他安全協(xié)議時(shí),包含 secure 選項(xiàng)的 cookie才能被發(fā)送至服務(wù)器。
默認(rèn)情況下,cookie不會(huì)帶secure選項(xiàng)(即為空)。所以默認(rèn)情況下,不管是HTTPS協(xié)議還是HTTP協(xié)議的請(qǐng)求,cookie 都會(huì)被發(fā)送至服務(wù)端。但要注意一點(diǎn),secure選項(xiàng)只是限定了在安全情況下才可以傳輸給服務(wù)端,但并不代表你不能看到這個(gè) cookie。
httponly選項(xiàng)用來設(shè)置cookie是否能通過 js 去訪問。默認(rèn)情況下,cookie不會(huì)帶httpOnly選項(xiàng)(即為空),所以默認(rèn)情況下,客戶端是可以通過js代碼去訪問(包括讀取、修改、刪除等)這個(gè)cookie的。當(dāng)cookie帶httpOnly選項(xiàng)時(shí),客戶端則無法通過js代碼去訪問(包括讀取、修改、刪除等)這個(gè)cookie。
在客戶端是不能通過js代碼去設(shè)置一個(gè)httpOnly類型的cookie的,這種類型的cookie只能通過服務(wù)端來設(shè)置。
5、 cookie的應(yīng)用
在進(jìn)行接口測(cè)試等工作中,經(jīng)常需要設(shè)置cookie,因?yàn)樵L問頁面有權(quán)限要求,很多用戶操作都對(duì)用戶的屬性有要求,因此,構(gòu)造cookie發(fā)送請(qǐng)求才能完成接口測(cè)試,下面以python的requests及urlib庫進(jìn)行接口測(cè)試舉例

其中add_header就是添加請(qǐng)求頭的方法。
6、 拾遺
app項(xiàng)目中在app請(qǐng)求中是沒有cookie的,直接將cookie的參數(shù)放在header里面進(jìn)行參數(shù)傳輸。