一、cookie 起源cookie 最早是網景公司的雇員 Lou Montulli 在1993年3月發明,後被 W3C 採納,目前 cookie 已經成為標準,所有的主流瀏覽器如 IE、Chrome、Firefox、Opera 等都支持。cookie 的誕生是由於 HTTP 協議的天生缺陷,HTTP...
一、cookie 起源
cookie 最早是網景公司的雇員 Lou Montulli 在1993年3月發明,後被 W3C 採納,目前 cookie 已經成為標準,所有的主流瀏覽器如 IE、Chrome、Firefox、Opera 等都支持。
cookie 的誕生是由於 HTTP 協議的天生缺陷,HTTP 是一種無狀態的協議,簡單的 Request 和 Response 一旦請求/響應結束,客戶端與伺服器端的連接就會關閉,再次交換數據需要建立新的連接。這就意味著伺服器無法從連接上跟蹤會話,即伺服器並不清楚是哪個客戶端。
一些典型應用如 登陸/購物車 就無法實現了。比如,用戶 A 在購物商城購買的商品都應該放在 A 的購物車內,不論是用戶 A 什麼時間購買的,這都是屬於同一個會話的,不能放入用戶 B 或用戶 C 的購物車內,這不屬於同一個會話。
基本的原理如圖
二、cookie 操作
對 cookie 的操作包括如下
- 名稱(Name)
- 值(Value)
- 域(Domain)
- 路徑(Path)
- 失效日期(Expires)
- 安全標誌(Secure)
- HttpOnly (僅伺服器端)
註意,cookie 多數時候由伺服器端創建,JS 也可以創建 cookie,但 HttpOnly 類型的 JS 無法創建。
瀏覽器提供的 cookie API (document.cookie)實在過於簡陋,可以稍封裝下,如以下採用setter/getter方式 cookie 函數就方便了許多
/* * JS 寫cookie和讀cookie操作 * * **取cookie** * cookie(name) * * **寫cookie** * cookie(name, value) * cookie(name, value, option) */ var cookie = function(name, value, option) { var doc = document if (value != undefined) { // set option = option || {} if (value === null) { value = '' option.expires = -1 } var expires = '' if (option.expires && (typeof option.expires == 'number' || option.expires.toUTCString)) { var date = new Date if (typeof option.expires == 'number') { date.setTime(date.getTime() + (option.expires * 24 * 60 * 60 * 1000)) } else { date = option.expires } // for IE expires = '; expires=' + date.toUTCString() } var path = option.path ? '; path=' + option.path : '' var domain = option.domain ? '; domain=' + option.domain : '' var secure = option.secure ? '; secure' : '' doc.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('') } else { // get var cookieValue = null if (doc.cookie && doc.cookie != '') { var cookies = doc.cookie.split(';') for (var i = 0; i < cookies.length; i++) { var cookie = $.trim(cookies[i]).split('=') if ( cookie[0] == name && cookie.length > 1 ) { try { cookieValue = decodeURIComponent(cookie[1]) } catch(e) { cookieValue = cookie[1] } break } } } return cookieValue } };
當然,還有更方便的 https://github.com/florian/cookie.js,提供了更多便捷函數。
三、cookie 類型
- 普通 cookie,伺服器端和 JS 都可以創建,JS 可以訪問
- HttpOnly cookie,只能由服務端創建,JS 是無法讀取的,主要基於安全考慮
- 安全的 cookie (僅https),伺服器端和 JS 都可以創建,JS 僅HTTPS下訪問
比如,在新浪雲上測試頁面:http://snandy.sinaapp.com/php/cookie.php,我種了 3 個 cookie,分別是 c1, c2, c3
$d1 = mktime(1,1,1,1,1,2018); // 普通cookie setcookie("c1", "Jack", $d1); // 安全的cookie,僅https,第6個參數 setcookie("c2", "John", $d1, NULL, NULL, TRUE); // HttpOnly cookie 第7個參數 setcookie("c3", "Resig", $d1, NULL, NULL, NULL, TRUE);
用 Firefox 訪問
我種的三個都有,saeut是新浪雲種的。
在 firebug 控制台輸入 document.cookie
可以看到,c2,c3 都是訪問不到的。c2 是 安全的cookie,需要在https協議下訪問,c3 則是 httpOnly 的,JS無法訪問,這個需要註意。
把訪問協議改成 https: https://snandy.sinaapp.com/php/cookie.php,firebug 切換到控制台再輸入 document.cookie,可以看到 c2 就可以訪問了
四、cookie 的坑
1. Cookie 太大或數量過多時頁面訪問報錯,比如會出現如下提示因此站點的 cookie 需要管理,不能隨意種 cookie。另外儘量指定path,將cookie限定在指定範圍內。
網站 browsercookielimits.squawky.net ,記錄了各瀏覽器 cookie 大小
2. 保存中文時需要Unicode編碼(encodeURIComponent),否則存的是亂碼