cookie
1、cookie基本介紹(客戶端會話技術)
cookie 是存儲在客戶端的,即瀏覽器,所以稱之為客戶端會話技術。而 session 是存儲在服務器端的,所以稱之為服務器端會話技術。
cookie是純文本,沒有可執行代碼,是指某些網站為了辨別用戶身份、進行 session 跟蹤而儲存在用戶本地終端(瀏覽器)上的數據(通常經過加密)。當用戶訪問了某個網站的時候,我們就可以通過cookie在訪問者電腦上存儲數據,或者某些網站為了辨別用戶身份、進行session 跟蹤而將數據儲存在用戶本地終端上(通常經過加密)。
cookie 默認是臨時存儲的,當關掉瀏覽器時自動銷毀(注意是關掉瀏覽器,如果只是關掉標簽頁,那cookie仍是存在的)。要想長時間保存一個cookie,就需要設置cookie的過期時間。當 Web 服務器創建了Cookies 后,只要在其有效期內,用戶訪問同一個 Web 服務器時(用戶訪問任何匹配該 Cookie 的路徑和域的頁面),瀏覽器首先要檢查本地的Cookies,并將其原樣發送給 Web 服務器。cookie是能保持 Web 瀏覽狀態的手段。
1.1、瀏覽器查看cookie
在谷歌瀏覽器開發模式的 application 下可以看到某個頁面所能訪問到的 cookie。注意,只能看到該網頁所能訪問到的 cookie 數據,而不是瀏覽器所有的cookie。

2、cookie的工作過程
當網頁要發 http 請求時,瀏覽器會先檢查是否有相應的 cookie,有則自動添加在request header中的cookie字段中。這些是瀏覽器自動幫我們做的,而且每一次http請求瀏覽器都會自動幫我們做。
存儲在cookie中的數據,每次都會被瀏覽器自動放在http請求中。如果這些數據并不是每個請求都需要發給服務端的數據,瀏覽器這設置自動處理無疑增加了網絡開銷。但如果這些數據是每個請求都需要發給服務端的數據(比如身份認證信息),瀏覽器這設置自動處理就大大免去了重復添加操作。所以對于那種設置“每次請求都要攜帶的信息(最典型的就是身份認證信息)”就特別適合放在cookie中,其他類型的數據就不適合了。
工作過程:
(1)首先,我們假設當前域名下還是沒有 Cookie 的
(2)接下來,瀏覽器發送了一個請求給服務器(這個請求是還沒帶上 Cookie 的)
(3)服務器設置 Cookie 并發送給瀏覽器(當然也可以不設置)
(4)瀏覽器將 Cookie 保存下來
(5)接下來,以后的每一次請求,都會帶上這些 Cookie,發送給服務器
3、cookie的相關概念
3.1、cookie的特點
- 過期時間:cookie 默認是存放在瀏覽器內存的,所以當會話結束(關閉瀏覽器)的時候即銷毀。當然也可以手動設置過期的時間,此時cookie將會被寫到硬盤的文件中,,持久化存儲,當時間到期才自動銷毀。
- 域:默認是當前頁面所在的域名。我們可以設置cookie生效的域(當前設置cookie所在域的子域),也就是說,我們能夠操作的cookie是當前域以及當前域下的所有子域
- path:默認是當前項目的虛擬目錄。
- 容量:一個瀏覽器能創建的 Cookie 數量最多為 300 個,并且每個不能超過 4KB,每個 Web 站點能設置的 Cookie 總數不能超過 20 個
- 安全性:因為cookie本身是存儲在瀏覽器端的,所以并不安全,并且容量有限,所以只適用于存儲少量的不太敏感的信息。
- cookie的存儲是以域名形式進行區分的,在同一瀏覽器下不同的域名下存儲的cookie是獨立的。不同的瀏覽器存放的cookie位置不一樣,也是不能通用的。
- cookie 必須在 HTML 文件的內容輸出之前設置。如果用戶在瀏覽器上設置了禁止 Cookie,則 Cookie 不能建立。
3.2、cookie的過期時間
cookie 默認是存放在瀏覽器內存的,所以當會話結束(關閉瀏覽器)的時候即銷毀。當然也可以手動設置過期的時間,此時cookie將會被寫到硬盤的文件中,持久化存儲,當時間到期才自動銷毀。
3.3、cookie的域(domain)
domain 默認值是當前頁面所在的域名。domain 指定了 cookie 將要被發送至哪個或哪些域中。默認情況下,domain 會被設置為創建該 cookie 的頁面所在的域名,所以當給相同域名發送請求時該 cookie 會被發送至服務器。瀏覽器會把 domain 的值與請求的域名做一個尾部比較(即從字符串的尾部開始比較),并將 domain 能匹配到域名的 cookie 發送至服務器。
(1)客戶端設置
document.cookie = "username=cfangxu;path=/;domain=qq.com"
上面將 domain 設置為 qq.com,即一級域名,表示訪問域名尾部是 qq.com 的網站時瀏覽器都會將該 cookie 帶上。path 值為 "/" 表示訪問 qq.com 域名下的根目錄下的都將能帶上該 cookie。
(2)服務端設置
Set-Cookie: username=cfangxu;path=/;domain=qq.com // 注:一定的是同域之間的訪問,不能把domain的值設置成非主域的域名。
3.4、cookie的路徑(path)
path 默認是當前前端項目的虛擬目錄。比如:http://localhost:8080/javawebtest02_war_exploded/test/test01.jsp ,javawebtest02_war_exploded是項目名,則path為javawebtest02_war_exploded。
因為安全方面的考慮,默認情況下,只有與創建 cookie 的頁面在同一個目錄或子目錄下的網頁才可以訪問。但 path 屬性可以為 cookie 指定路徑,domain 和 path 加起來構成了URL,表示當瀏覽器在訪問該 URL 下的網站或者 URL 帶有這個前綴的網站時都將會帶上該 cookie 。
(1)客戶端設置
最常用的例子就是讓 cookie 在根目錄下,這樣不管是哪個子頁面創建的 cookie,該域名下的所有頁面都可以訪問到了。
document.cookie = "username=cfangxu; path=/"
(2)服務器端設置
Set-Cookie:name=cfangxu; path=/blog
如上設置:path 選項值會與 /blog,/blogrool 等等相匹配;任何以 /blog 開頭的選項都是合法的。需要注意的是,只有在 domain 選項核實完畢之后才會對 path 屬性進行比較。path 屬性的默認值是發送 Set-Cookie 消息頭所對應的 URL 中的 path 部分。
3.5、domain和path的關系(domain+path=URL)
domain是域名,path是路徑,兩者加起來就構成了 URL,domain和path一起來限制 cookie 能被哪些 URL 訪問。
所以domain和path兩個選項共同決定了cookie何時被瀏覽器自動添加到請求頭部中發送出去。如果沒有設置這兩個選項,則會使用默認值。domain的默認值為設置該cookie的網頁所在的域名,path默認值為設置該cookie的網頁所在的目錄。
4、JS操作cookie
JavaScript 可以使用 document.cookie 屬性來創建 、讀取、及刪除 cookie。
瀏覽器端可以設置cookie 的下列選項:expires、domain、path、secure(有條件:只有在https協議的網頁中,客戶端設置secure類型的 cookie 才能成功),但無法設置HttpOnly選項。
4.1、創建cookie
document.cookie="username=John Doe";
添加過期時間(以 UTC 或 GMT 時間)。默認情況下,cookie 在瀏覽器關閉時刪除
document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT";
添加瀏覽器 cookie 的路徑。默認情況下,cookie 屬于當前頁面。
document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";
4.2、讀取cookie
通過document.cookie來獲取當前網站下的cookie的時候,得到的是字符串形式的值,它包含了當前網站下所有的cookie,這個方法只能獲取非 HttpOnly 類型的cookie。它會把所有的cookie通過一個分號+空格的形式串聯起來,例如:username=chenfangxu; job=coding
var x = document.cookie;
4.3、修改 cookie
要想修改一個cookie,只需要重新賦值就行,舊的值會被新的值覆蓋。但要注意一點,在設置新cookie時,path/domain這幾個選項一定要舊cookie 保持一樣。否則不會修改舊值,而是添加了一個新的 cookie。
document.cookie="username=John Smith; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";
4.4、刪除 cookie
把要刪除的cookie的過期時間設置成已過去的時間,path/domain/這幾個選項一定要舊cookie 保持一樣。
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
5、Java操作cookie
服務端可以設置cookie 的所有選項:expires、domain、path、secure、HttpOnly。
5.1、設置并返回cookie
- 設置cookie:Cookie cookie = new Cookie("key", "value");
- 給瀏覽器返回cookie:response.addCookie(cookie); 即發送 Cookie 到 HTTP 響應頭
- 讀取瀏覽器發送的cookie:Cookie[] cookies = request.getCookies();
代碼示例:
@WebServlet("/cookieTest01")
public class CookieTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//讀取客戶端發送的cookie
Cookie[] cookies = req.getCookies();
if(cookies != null) {
for (int i = 0; i < cookies.length; i++) {
String name = cookies[i].getName();
String val = cookies[i].getValue();
System.out.println(name + ": " + val);
}
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//設置cookie。可以一次性添加多個cookie,只需重復下面操作先創建然后添加至response即可
Cookie cookie = new Cookie("cookieTest","cookieTestValue");
//給客戶端返回cookie
response.addCookie(cookie);
}
}
當我們設置了 cookie,并且給客戶端返回時,在瀏覽器的可以看到該請求的響應頭上有 set-cookie 頭信息。在設置了多個cookie時,每個cookie將以分號 ; 分隔開。

瀏覽器獲取到 set-cookie 響應頭時就會自動給瀏覽器添加 cookie 信息,并且在下次發出請求時會自動把 cookie 信息給帶上,如下:

5.1.1、cookie中存取中文
在 tomcat8 之后的版本,可以直接往 cookie 中存儲中文數據。但在 tomcat8 之前,cookie 是不能直接存儲中文的,所以我們需要將中文數據先編碼然后放在cookie當中,在從瀏覽器中拿取時,也需要先解碼后才能拿到正確數據。
我們可以采用 URL 編碼來對中文數據進行編碼:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String cookieStr = java.net.URLEncoder.encode("cookie的中文值","UTF-8") //將中文數據編碼后再放入cookie Cookie cookie = new Cookie("cookieTest", cookieStr); response.addCookie(cookie); }
在讀取cookie時,可以使用 URL 解碼:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("讀取cookie:"); Cookie[] cookies = req.getCookies(); if(cookies != null) { for (int i = 0; i < cookies.length; i++) { String name = cookies[i].getName(); String val = cookies[i].getValue(); System.out.println(name + ": " + java.net.URLDecoder.decode(val,"UTF-8")); //使用java.net.URLDecoder.decode() 進行解碼 } } }
5.2、設置cookie的過期時間
通過 setMaxAge(int 秒數) 方法可以設置 cookie 過期的時間(以秒為單位),該方法指定了該 cookie 將在指定的秒數時間過后被銷毀。如果不這樣設置,cookie 只會在當前 session 會話中持續有效。
public void setMaxAge(int 秒數);
setMaxAge() 方法的參數可以是正數、負數、0。當為正數時,表示指定秒數過后該 cookie 被自動銷毀;當為負數時,表示 cookie 的過期時間為默認值,即瀏覽器關閉時;當為0時,表示刪除該 cookie。
代碼示例:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Cookie cookie = new Cookie("cookieName","cookieValue"); cookie.setMaxAge(30); resp.addCookie(cookie); }
上面設置了過期時間時,可以看到響應頭 set-cookie 里有指定該cookie的過期時間:

我們指定了30秒,在30秒過后你可以看到該 cookie 在瀏覽器中會被自動銷毀,此時在瀏覽器往服務器發請求時也不會帶上該 cookie。但是在 30 秒之內,就算關閉了瀏覽器,此時該 cookie 仍是存在的,在瀏覽器往服務器發請求時也是會帶上該 cookie 的。
5.3、刪除cookie
服務器端可以通過以下方法來刪除瀏覽器端的 cookie,實際上是設置該 cookie 的過期時間為0。
步驟如下:
- 讀取一個現有的 cookie
- 使用 setMaxAge(0) 方法將該cookie的過期時間設為0
- 把這個 cookie 添加到響應頭
代碼示例:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //讀取瀏覽器發送的全部cookie Cookie[] cookies = request.getCookies(); if(cookies != null) { for (int i = 0; i < cookies.length; i++) { if(cookies[i].getName().equals("cookieName")) { cookies[i].setMaxAge(0); //設置該 cookie 的過期時間為0,即刪除該cookie response.addCookie(cookies[i]); //將該cookie添加至響應消息,瀏覽器將自動刪除該cookie } } } }
在請求上面servlet時,服務器將會返回該cookie,同時將該cookie的過期時間設為0,此時瀏覽器將會自動將該cookie在瀏覽器端刪除。

5.4、設置cookie的path
cookieObj.setPath() 方法可設置cookie的path。如果不指定路徑,則 path 的值為當前頁面的項目的虛擬目錄。比如:http://localhost:8080/javawebtest02_war_exploded/test/test01.jsp ,javawebtest02_war_exploded是項目名,則path為javawebtest02_war_exploded。
public void setPath(String uri)
我們可以使用 cookieObj.setPath("/"); 來設置該 cookie 在當前頁面的域名下的所有頁面都可訪問該 cookie。

浙公網安備 33010602011771號