早期互聯網只是用于簡單的頁面瀏覽,并沒有互動,服務器也無法知道不同的請求是否來自同一個瀏覽器,不知道某用戶上一次做了什么,每次請求都是相互完全獨立的,這也是 HTTP 協議無狀態特征的表現,這種缺陷顯然無法滿足互動式 Web 發展的需求,Cookie 作為一種解決這一問題的方案,被當時最強大的網景瀏覽器公司提出,
一、Cookie敘述
Cookie 可以理解成瀏覽器的身份證,不同站點會根據實際情況,發放一個唯一的身份證或不發放,當再次訪問相同站點時,按照約定要帶上這個身份證來享受部分特權,如果身份證丟了,那就要重新登記辦理,
Cookie 資訊是由客戶端瀏覽器自身維護的,不同的瀏覽器有不同的客戶端本地存盤方式,Chrome 和 Firefox 使用 SQLite 存盤,IE 使用的是文本格式,Cookie 里面重要的 key&value 都是被瀏覽器加密存放的,只有通過給定的 API 方式才能獲取存入的原始資料,默認情況下,Cookie 資訊會隨著瀏覽器行程的結束而從記憶體中銷毀,如果由于某些需求,服務器端設定了 Cookie 的存活時間,那么這個 Cookie 就會以某種形式被存盤在磁盤上,在有效存活期內不會被清理,可以被重復使用并更新其生命周期,
1.1 觀察Cookie在HTTP資料包中的互動
這里以 http://www.website.com/bbs/ 站點為例,說明 Cookie 在 HTTP 協議包里是如何傳輸的,
第一次請求 bbs 首頁 /bbs/ 時,在請求資料包的 header 部分是沒有 Cookie 資訊的,這時,因為某些功能需要,站點會要求在瀏覽器本地存盤 Cookies,如下面第一次互動請求登陸頁面,本地瀏覽器會存盤三個變數: phpbb3_lhc4d_u , phpbb3_lhc4d_k , phpbb3_lhc4d_sid ,在這里要重點關注 phpbb3_lhc4d_sid 這個變數,它存盤的是服務器端 SessionID 的值(也可以稱呼它為會話識別符號),
GET /bbs/ HTTP/1.1
Host: www.website.com.cn
Upgrade-Insecure-Requests: 1
User-Agent: Mosilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://www.website.com.cn/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close
HTTP/1.1 200 OK
Date: Mon, 21 Oct 2019 03:04:44 GMT
Server: Apache
X-Powered-By: PHP/5.5.38-1~dotdeb+7.1
Set-Cookie: phpbb3_lhc4d_u=1; expires=Tue, 20-Oct-2020 03:04:44 GMT; path=/; domain=www.website.com.cn; HttpOnly
Set-Cookie: phpbb3_lhc4d_k=; expires=Tue, 20-Oct-2020 03:04:44 GMT; path=/; domain=www.website.com.cn; HttpOnly
Set-Cookie: phpbb3_lhc4d_sid=8fedbe0e849ab04df7a698b54d011b16; expires=Tue, 20-Oct-2020 03:04:44 GMT; path=/; domain=www.website.com.cn; HttpOnly
Cache-Control: private, no-cache="set-cookie"
Expires: Mon, 21 Oct 2019 03:04:44 GMT
Referer-Policy: same-origin
X-Frame-Options: sameorigin
Vary: Accept-Encoding
Content-Length: 9110
Connection: close
Content-Type: text/html; charset=UTF-8
重繪頁面,再次請求同一個頁面,可以發現瀏覽器會自動把之前存盤在本地的對應站點 Cookies 全部提交過去,這里提一下,每一個 Cookie 都是有大小限制的,大約在 4k 左右,
GET /bbs/ HTTP/1.1
Host: www.website.com.cn
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mosilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://www.website.com.cn/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: phpbb3_lhc4d_u=1; phpbb3_ihc4d_k=; phpbb3_lhc4d_sid=8fedbe0e849ab04df7a698b54d011b16
Connection: close
HTTP/1.1 200 OK
Date: Mon, 21 Oct 2019 03:05:16 GMT
Server: Apache
X-Powered-By: PHP/5.5.38-1~dotdeb+7.1
Cache-Control: private, no-cache="set-cookie"
Expires: Mon, 21 Oct 2019 03:05:16 GMT
Referer-Policy: same-origin
X-Frame-Options: sameorigin
Vary: Accept-Encoding
Content-Length: 8435
Connection: close
Content-Type: text/html; charset=UTF-8
輸入正確的賬號資訊進入 bbs 內部后,會發現服務器更新了存盤在本地 Cookie 中的 phpbb3_lhc4d_sid 資訊,它是你能留在 bbs 內部板塊的通行證,只要訪問的時候帶上這個 Cookies 就可以暢通無阻,
POST /bbs/ucp/php?mode=login HTTP/1.1
Host: www.website.com.cn
Content-Length: 94
Cache-Control: max-age=0
Origin: http://www.website.com.cn
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mosilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://www.website.com.cn/bbs/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: phpbb3_lhc4d_u=1; phpbb3_ihc4d_k=; phpbb3_lhc4d_sid=8fedbe0e849ab04df7a698b54d011b16
Connection: close
username=***********&password=**************************&login=%E7%99%BB%E5%BD%95&redirect=.%2Findex.php%3F
HTTP/1.1 302 Found
Date: Mon, 21 Oct 2019 03:05:48 GMT
Server: Apache
X-Powered-By: PHP/5.5.38-1~dotdeb+7.1
Set-Cookie: phpbb3_lhc4d_u=77; expires=Tue, 20-Oct-2020 03:05:48 GMT; path=/; domain=www.website.com.cn; HttpOnly
Set-Cookie: phpbb3_lhc4d_k=; expires=Tue, 20-Oct-2020 03:05:48 GMT; path=/; domain=www.website.com.cn; HttpOnly
Set-Cookie: phpbb3_lhc4d_sid=bdabd760e3a87aa6b0dfb517c8c7d90a; expires=Tue, 20-Oct-2020 03:05:48 GMT; path=/; domain=www.website.com.cn; HttpOnly
Location: http://www.website.com.cn/bbs/index.php?&sid=bdabd760e3a87aa6b0dfb517c8c7d90a
Cache-Control: max-age=86400
Expires: Tue, 22 Oct 2019 03:05:48 GMT
Referer-Policy: same-origin
X-Frame-Options: sameorigin
Vary: Accept-Encoding
Content-Length: 0
Connection: close
Content-Type: text/html
GET /bbs/index.php HTTP/1.1
Host: www.website.com.cn
Upgrade-Insecure-Requests: 1
User-Agent: Mosilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://www.website.com.cn/bbs/index.php?&sid=bdabd760e3a87aa6b0dfb517c8c7d90a
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: phpbb3_lhc4d_u=1; phpbb3_ihc4d_k=; phpbb3_lhc4d_sid=bdabd760e3a87aa6b0dfb517c8c7d90a
Connection: close
HTTP/1.1 200 OK
Date: Mon, 21 Oct 2019 03:06:16 GMT
Server: Apache
X-Powered-By: PHP/5.5.38-1~dotdeb+7.1
Cache-Control: private, no-cache="set-cookie"
Expires: Mon, 21 Oct 2019 03:06:16 GMT
Referer-Policy: same-origin
X-Frame-Options: sameorigin
Vary: Accept-Encoding
Content-Length: 37722
Connection: close
Content-Type: text/html; charset=UTF-8
分析上述 HTTP 資料包的互動:
- Cookie 是使用 HTTP 的頭部來傳遞和交換資訊的;
- Set-Cookie 是服務器端給瀏覽器下發指令的關鍵字,可以帶上一些控制屬性;
- Cookie 是瀏覽器端發送給服務器端訊息欄位,它只能是 name=value 格式,無法帶上其他屬性,
二、Cookie有哪些屬性
在 RFC6265 中規定,通常 Set-Cookie 回應頭部包含頭部名稱為「Set-Cookie:尾隨的 Cookie」,尾隨的 Cookie 除了 name, value 這兩個必備屬性外,還有幾個其他的控制屬性可選,相關描述摘錄如下:
| 屬性 | 描述 |
|---|---|
| 必須屬性 | 變數名稱:值 |
| 可選屬性 | 描述摘錄 |
| expires 過期屬性 |
如果這個屬性的值不能被轉換為日期,客戶端會忽略該屬性, 當同一個 Cookie 兩次請求的 expires 值不相同時,新的可能會替換舊的, |
| max-age 最大快取 時間屬性 |
相對過期時間,以秒為單位, 如果該屬性的值不是數字,客戶端將不做處理,(max-age 優先級大于 expires) |
| domain 域屬性 |
如果沒有設定 Cookie 的 domain 值,該屬性的默認值就是創建 Cookie 的網頁所在的服務器域名, |
| path 路徑屬性 |
Cookie 的適用范圍為路徑設定所限制, 如果服務器忽略路徑屬性,用戶客戶端會將請求 uri 路徑元素的名錄當做預設值, |
| secure 安全屬性 |
它指定了在網路上如何傳輸 Cookie 值, 默認情況下,Cookie 是不安全的,也就是說,它們是通過一個普通的、不安全的 HTTP 鏈接傳輸的, 但是如果將 Cookie 標記為安全的,那么它將只在瀏覽器和服務器通過 HTTPS 或其他安全協議鏈接時才被傳輸, 這個屬性只能保證 Cookie 是保密的, |
| HttpOnly 屬性 |
HttpOnly 屬性限制 Cookie 的 HTTP 請求的適用范圍,只能通過 HTTP 訪問,不能通過 document.cookie 獲取設定為 HttpOnly 的鍵值,防止 XSS 讀取 Cookie, Cookie 可以同時擁有 HttpOnly 以及安全屬性, |
三、Cookie的應用場景
3.1 HTTP會話狀態保持
單純的Cookie會話管理——

相對安全的Cookie會話機制——

在功能實作上,兩者都沒有問題,但在實際使用中會發現 Cookie 本身大小數量的限制和資訊本地保存會帶來一定的安全問題(如可能會暴露給攻擊者,或被攻擊者重放),一般使用中不推薦把敏感資訊存放于 Cookie 中,而是采用存盤會話識別符號(SessionID)到 Cookie 里的方式,服務器端可以通過獲取這個會話識別符號(SessionID)關聯當前狀態資訊,當然了,使用會話識別符號并非沒有風險,相對于前一種方式已是個好的改善,
打個比方,假設瀏覽器對應自然人,Cookie 對應身份證,而 Web 服務器端對應的是戶籍管理處,那么,Web 服務器(戶籍管理處)需要負責給瀏覽器(自然人)發放 Cookie(身份證),后期的會話鑒別就是通過保存在客戶端瀏覽器的 Cookie(身份證姓名和號碼)里的「會話識別符號」實作的,所有的敏感資訊都存盤在服務器端(戶籍管理處),而非交給第三方的瀏覽器來保管,
3.2 基于Cookie的SSO單點登錄
同域和非同域下SSO單點登錄
在同域下實作 Cookies 單點登錄相對而言簡單一些,將 Cookie 的 domain 屬性配置好父域名,如 .website.com.cn ,那么這個 Cookie 就可以被類似 a.website.com.cn ,b.website.com.cn ,sso.website.com.cn ,website.com.cn 共享使用,有一點需要特別注意,瀏覽器請求子域會帶上父域的 Cookie,反之則不會,按照約定,我們把需要共享的 Cookie 資訊寫入到 website.com.cn 這個域名下即可,

以上討論的是同域情況下的 SSO 單點登錄程序,那么跨域情況下又是怎么個原理呢?繼續來看流程圖,相比上述同域情況會多了跳來跳去的動作,

3.3 跟蹤分析用戶行為
「大資料」顛覆了某些舊的束縛,有能力去分析全部資料,可得出準確的大方向,而不再僅憑隨機采樣資料做分析,在互聯網行業,「大資料」表現在采集和分析網路用戶行為資料,并推送需求上,說到網路用戶行為資料的采集,就不能不談談 Cookie 在此所扮演的另類角色,
客戶端訪問個性化設定
網站的各項配置引數可以存盤在瀏覽器本地 Cookies 中,當客戶端瀏覽器再次訪問此站點時,直接通過讀取 Cookies 資訊即可完成相關的個性化配置,當然,局限性也很明顯,Cookies 到期失效或換一臺電腦,效果就沒有了,這是針對臨時用戶而言的,有會員注冊功能的站點,一般將配置保存在 Web 服務器本地資料庫,這是持久存在的,
搜索引擎&定向廣告推送
在搜索引擎或購物站點搜索產品資訊后,再瀏覽其他網頁時,經常在其廣告區域顯示曾經搜索過的產品或相關資訊,哪天小伙伴借你電腦臨時一用,打開游覽器,你的隱私可能就暴露了,很是討厭,而這是 Cookie 的功勞,

網路廣告公司資訊推廣
還有一種可能,你打開的某站點很有可能還內嵌了一種叫做網頁臭蟲的圖片,該圖片透明且只有一個像素大小,我們稱呼它為 Pixel Code,其作用是向所有訪問過此頁面的客戶端寫入定制的 Cookie (通過不同站點收集用戶愛好習慣),當你訪問與網路廣告推廣有合作的購物站點時,這些 Cookie 資訊就會被讀取并被有針對性地推薦廣告,整個流程和上面的搜索引擎&定向廣告類似,在此不再作圖贅述了,
四、Cookie的安全問題探討
作為一個和 HTTP 協議打交道多年的安全從業者,還是忍不住想討論下這個問題——
我們知道 Cookie 是保存在用戶本地的,由各自的瀏覽器自行維護,拿 Chrome 瀏覽器來說,用戶可以直接在瀏覽器內輸入 chrome://settings/siteData 來訪問它的 Cookies 存盤資訊,這種方式是通過瀏覽器 API 獲取,可以完整地看到原始 value 資訊,如果用戶想通過其他手段查看,還可以通過 chrome://version/ 發現資料存盤的位置,仔細查看后,不難發現,%LOCALAPPDATA%\Google\Chrome\UserData\Default\Cookies 就是它的 Cookies 存盤檔案,這是一個 SQLite 輕型資料庫,通過工具打開查詢后可發現,domain 是 baidu 的都可以被搜索出來,如下圖,這里可以看到,name=value 的 value 部分被瀏覽器進行了一次加密存盤處理,

聊完 Chrome 的本地存盤,再說說 Cookie 本身的特點,Cookie 通常可能記錄了用戶賬號 ID、密碼、會話識別符號 SessionID,這些資訊可能是加密,也可能是未加密的,加密存盤只能說明其在安全上做了些功課,但被攻擊者截獲(抓包、XSS)后,是否加密并無太大意義,攻擊者無需看懂那串密語,只需要把這些資訊照葫蘆畫瓢丟給服務器,就可以實作越權操作了,而這些安全性問題,可以閱讀相關詞條(見Ref1)了解學習,
(易樹國 | 天存資訊)
Ref
- ‘cookie 儲存在用戶本地終端上的資料’ - 百科詞條
- ‘HTTP State Management Mechanism’ - RFC6265
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/288267.html
標籤:其他
