HTTP協議是無狀態協議。HTTP協議自身不對請求和響應之間的通訊狀態進行保存。
因而爲了實現指望的保持狀態功能,引入了cookie技術。git
Cookie會根據從服務器端發送的響應報文內的Set-Cookie的首部字段信息,通知客戶端保存Cookie。下次客戶端再往該服務器發送請求時,自動在請求報文中加入Cookie再發送。
沒有信息狀態下的請求
存有信息狀態下的請求github
服務器端像客戶端發送Cookie是經過HTTP響應報文實現的,在Set-Cookie中設置須要像客戶端發送的cookie,cookie格式以下:
Set-Cookie: "name=value;domain=.domain.com;path=/;expires=Sat, 11 Jun 2016 11:29:42 GMT;HttpOnly;secure"
其中name=value是必選項,其它都是可選項。ajax
該Cookie的名稱,一旦建立,名稱便不可更改數據庫
該Cookie的值,若是值爲Unicode字符,須要爲字符編碼,若是值爲二進制數據,則須要使用BASE64編碼瀏覽器
能夠訪問該Cookie的域名。若是設置爲」.google.com」,則全部以」google.com」結尾的域名均可以訪問該Cookie。注意第一個字符必須爲「.」
這個domain稍做解釋:安全
1. 非頂級域名,如二級域名或者三級域名,設置的cookie的domain只能爲頂級域名或者二級域名或者三級域名自己,不能設置其餘二級域名的cookie,不然cookie沒法生成。 2. 頂級域名只能設置domain爲頂級域名,不能設置爲二級域名或者三級域名,不然cookie沒法生成。 3. 二級域名能讀取設置了domain爲頂級域名或者自身的cookie,不能讀取其餘二級域名domain的cookie。因此要想cookie在多個二級域名中共享,須要設置domain爲頂級域名,這樣就能夠在全部二級域名裏面或者到這個cookie的值了。
頂級域名只能獲取到domain設置爲頂級域名的cookie,其餘domain設置爲二級域名的沒法獲取。服務器
path字段爲能夠訪問此cookie的頁面路徑。 好比domain是abc.com, path是/detail,那麼只有/detail 路徑下的頁面能夠讀取此cookie。cookie
1. 該Cookie失效時間,單位秒。若是爲正數,則Cookie在maxAge秒以後失效。 2. 若是爲負數,該Cookie爲臨時Cookie,關閉瀏覽器即失效,瀏覽器也不會以任何形式保存Cookie. 3. 若是爲0,表示刪除Cookie。默認是-1
cookie的大小session
cookie的httponly屬性。若此屬性爲true,則只有在http請求頭中會帶有此cookie的信息,而不能經過document.cookie來訪問此cookie。dom
設置是否只能經過https來傳遞此條cookie
cookie有兩種類型:
不設置過時時間,則表示這個cookie生命週期爲瀏覽器會話期間,只要關閉瀏覽器窗口,cookie就消失了。這種生命期爲瀏覽會話期的cookie被稱爲會話cookie。會話cookie通常不保存在硬盤上而是保存在內存裏。能夠類比於本地存儲的sessionstore
設置了過時時間,瀏覽器就會把cookie保存到硬盤上,關閉後再次打開瀏覽器,這些cookie依然有效直到超過設定的過時時間。
存儲在硬盤上的cookie能夠在不一樣的瀏覽器進程間共享,好比兩個IE窗口。而對於保存在內存的cookie,不一樣的瀏覽器有不一樣的處理方式。能夠類比於本地存儲的localstore
//讀取cookie,一次性獲取全部cookie。 console.log(document.cookie); //每一個cookie都是以鍵值對的形式存在,而且經過;分隔。 "BAIDUID=9BD404162B2978E266B82B0D052A12D7:FG=1;BIDUPSID=605A0EB7E85170299BCFFF6C2B042840; "
在cookie 的名或值中不能使用分號(;)、逗號(,)、等號(=)以及空格。在cookie的名中作到這點很容易,但要保存的值是不肯定的。如何來存儲這些值呢?方 法是用escape()函數進行編碼,它能將一些特殊符號使用十六進制表示,例如空格將會編碼爲「20%」,從而能夠存儲於cookie值中,並且使用此種方案還能夠避免中文亂碼的出現。
document.cookie="str="+escape("I love ajax"); // document.cookie="str=I%20love%20ajax";
當使用escape()編碼後,在取出值之後須要使用unescape()進行解碼才能獲得原來的cookie值
function setCookie(name,value) { var Days = 30; var exp = new Date(); exp.setTime(exp.getTime() + Days*24*60*60*1000); document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString(); }
要想修改一個cookie,只須要從新賦值就行,舊的值會被新的值覆蓋。但要注意一點,在設置新cookie時,path/domain這幾個選項必定要舊cookie 保持同樣。不然不會修改舊值,而是添加了一個新的 cookie。
刪除 cookie刪除一個cookie 也挺簡單,也是從新賦值,只要將這個新cookie的expires 選項設置爲一個過去的時間點就好了。但一樣要注意,path/domain/這幾個選項必定要舊cookie 保持同樣。
//獲取當前時間 var date=new Date(); //將date設置爲過去的時間 date.setTime(date.getTime()-10000); //將userId這個cookie刪除 document.cookie="userId=828; expires="+date.toGMTString();
有一個坑,設置cookie時,和刪除cookie時,必需要保持如出一轍!!!
登陸時候用cookie的話,安全性問題怎麼解決?
First:
把用戶對象(包含了用戶ID、用戶名、是否登陸..)序列化成字符串再加密存入Cookie。 密鑰是:客戶端IP+瀏覽器Agent+用戶標識+固定的私有密鑰 當cookie被竊取後,只要任一信息不匹配,就沒法解密cookie,進而也就不能登陸了。 這樣作的缺點是IP不能變更、頻繁加密解密會加劇CPU負擔
Second:
將用戶的認證信息保存在一個cookie中,具體以下: 1.cookie名:uid。推薦進行加密,好比MD5(‘站點名稱’)等。 2.cookie值:登陸名|有效時間Expires|hash值。hash值能夠由」登陸名+有效時間Expires+用戶密碼(加密後的)的前幾位 +salt」 (salt是保證在服務器端站點配置文件中的隨機數)
這樣子設計有如下幾個優勢:
1.即便數據庫被盜了,盜用者仍是沒法登陸到系統,由於組成cookie值的salt是保證在服務器站點配置文件中而非數據 庫。
2.若是帳戶被盜了,用戶修改密碼,可使盜用者的cookie值無效。
3.若是服務器端的數據庫被盜了,經過修改salt值可使全部用戶的cookie值無效,迫使用戶從新登陸系統。
4.有效時間Expires能夠設置爲當前時間+過去時間(好比2天),這樣能夠保證每次登陸的cookie值都不同,防止盜用者 窺探到本身的cookie值後做爲後門,長期登陸。
參考連接:聊一聊 cookie