什麼是Cookie?
HTTP協議本身是無狀態的。什麼是無狀態呢,即服務器無法判斷用戶身份。Cookie實際上是一小段的文本信息(key-value格式)。客戶端向服務器發起請求,如果服務器需要記錄該用戶狀態,就使用response向客戶端瀏覽器頒發一個Cookie。客戶端瀏覽器會把Cookie保存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。服務器檢查該Cookie,以此來辨認用戶狀態。
cookie機制
當用戶第一次訪問並登陸一個網站的時候,cookie的設置以及發送會經歷以下4個步驟:
客戶端發送一個請求到服務器 --》 服務器發送一個HttpResponse響應到客戶端,其中包含Set-Cookie的頭部 --》 客戶端保存cookie,之後向服務器發送請求時,HttpRequest請求中會包含一個Cookie的頭部 --》服務器返回響應數據
爲了探究這個過程,寫了代碼進行測試,如下:
我在doGet方法中,new了一個Cookie對象並將其加入到了HttpResponse對象中
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie cookie = new Cookie("mcrwayfun",System.currentTimeMillis()+"");
// 設置生命週期爲MAX_VALUE
cookie.setMaxAge(Integer.MAX_VALUE);
resp.addCookie(cookie);
}
瀏覽器輸入地址進行訪問,結果如圖所示:
可見Response Headers中包含Set-Cookie頭部,而Request Headers中包含了Cookie頭部。name和value正是上述設置的。
cookie屬性項
屬性項 | 屬性項介紹 |
---|---|
NAME=VALUE | 鍵值對,可以設置要保存的 Key/Value,注意這裏的 NAME 不能和其他屬性項的名字一樣 |
Expires | 過期時間,在設置的某個時間點後該 Cookie 就會失效 |
Domain | 生成該 Cookie 的域名,如 domain="www.baidu.com" |
Path | 該 Cookie 是在當前的哪個路徑下生成的,如 path=/wp-admin/ |
Secure | 如果設置了這個屬性,那麼只會在 SSH 連接時纔會回傳該 Cookie |
Expires
該屬性用來設置Cookie的有效期。Cookie中的maxAge用來表示該屬性,單位爲秒。Cookie中通過getMaxAge()和setMaxAge(int maxAge)來讀寫該屬性。maxAge有3種值,分別爲正數,負數和0。
如果maxAge屬性爲正數,則表示該Cookie會在maxAge秒之後自動失效。瀏覽器會將maxAge爲正數的Cookie持久化,即寫到對應的Cookie文件中(每個瀏覽器存儲的位置不一致)。無論客戶關閉了瀏覽器還是電腦,只要還在maxAge秒之前,登錄網站時該Cookie仍然有效。下面代碼中的Cookie信息將永遠有效。
Cookie cookie = new Cookie("mcrwayfun",System.currentTimeMillis()+"");
// 設置生命週期爲MAX_VALUE,永久有效
cookie.setMaxAge(Integer.MAX_VALUE);
resp.addCookie(cookie);
當maxAge屬性爲負數,則表示該Cookie只是一個臨時Cookie,不會被持久化,僅在本瀏覽器窗口或者本窗口打開的子窗口中有效,關閉瀏覽器後該Cookie立即失效。
Cookie cookie = new Cookie("mcrwayfun",System.currentTimeMillis()+"");
// MaxAge爲負數,是一個臨時Cookie,不會持久化
cookie.setMaxAge(-1);
resp.addCookie(cookie);
可以看到,當MaxAge爲-1時,時間已經過期
當maxAge爲0時,表示立即刪除Cookie
Cookie[] cookies = req.getCookies();
Cookie cookie = null;
// get Cookie
for (Cookie ck : cookies) {
if ("mcrwayfun".equals(ck.getName())) {
cookie = ck;
break;
}
}
if (null != cookie) {
// 刪除一個cookie
cookie.setMaxAge(0);
resp.addCookie(cookie);
}
那麼maxAge設置爲負值和0到底有什麼區別呢?
maxAge設置爲0表示立即刪除該Cookie,如果在debug的模式下,執行上述方法,可以看見cookie立即被刪除了。
maxAge設置爲負數,能看到Expires屬性改變了,但Cookie仍然會存在一段時間直到關閉瀏覽器或者重新打開瀏覽器。
修改或者刪除Cookie
HttpServletResponse提供的Cookie操作只有一個addCookie(Cookie cookie),所以想要修改Cookie只能使用一個同名的Cookie來覆蓋原先的Cookie。如果要刪除某個Cookie,則只需要新建一個同名的Cookie,並將maxAge設置爲0,並覆蓋原來的Cookie即可。
新建的Cookie,除了value、maxAge之外的屬性,比如name、path、domain都必須與原來的一致才能達到修改或者刪除的效果。否則,瀏覽器將視爲兩個不同的Cookie不予覆蓋。
值得注意的是,從客戶端讀取Cookie時,包括maxAge在內的其他屬性都是不可讀的,也不會被提交。瀏覽器提交Cookie時只會提交name和value屬性,maxAge屬性只被瀏覽器用來判斷Cookie是否過期,而不能用服務端來判斷。
我們無法在服務端通過cookie.getMaxAge()來判斷該cookie是否過期,maxAge只是一個只讀屬性,值永遠爲-1。當cookie過期時,瀏覽器在與後臺交互時會自動篩選過期cookie,過期了的cookie就不會被攜帶了。
Cookie的域名
Cookie是不可以跨域名的,隱私安全機制禁止網站非法獲取其他網站的Cookie。
正常情況下,同一個一級域名下的兩個二級域名也不能交互使用Cookie,比如test1.mcrwayfun.com和test2.mcrwayfun.com,因爲二者的域名不完全相同。如果想要mcrwayfun.com名下的二級域名都可以使用該Cookie,需要設置Cookie的domain參數爲.mcrwayfun.com,這樣使用test1.mcrwayfun.com和test2.mcrwayfun.com就能訪問同一個cookie
一級域名又稱爲頂級域名,一般由字符串+後綴組成。熟悉的一級域名有baidu.com,qq.com。com,cn,net等均是常見的後綴。
二級域名是在一級域名下衍生的,比如有個一級域名爲mcrfun.com,則blog.mcrfun.com和www.mcrfun.com均是其衍生出來的二級域名。
Cookie的路徑
path屬性決定允許訪問Cookie的路徑。比如,設置爲"/"表示允許所有路徑都可以使用Cookie