Cookie 指得是儲存在Client (用戶)端上的資料,是一種在伺服器與瀏覽器之間交換訊息的方法,按照Client 端儲存的位置可分為記憶體Cookie 和硬碟Cookie。
記憶體Cookie 由瀏覽器維護,儲存在記憶體中,瀏覽器關閉即消失,存在時間短暫,也稱為非持久Cookie;硬碟Cookie 儲存在硬碟裡,有過期時間,除非使用者手動清理或到了過期時間,否則硬碟Cookie 不會清除,存在時間較長,也稱為為持久Cookie。
因為HTTP 協定是無狀態的,Server 不知道使用者上一次做了什麼,這嚴重阻礙了互動式Web 應用程式的實現,所以Cookie 就是用來繞開HTTP 的無狀態性的一種手段,Server 可以設定或讀取Cookie 中包含的資訊,藉此維護使用者跟Server 對談中的狀態。
若要在Spring Boot 中設置Cookie,就要使用到HttpServletResponse 的addCookie() 方法,該方法就是將一個Cookie 物件加入Response 中。
@RequestMapping(value = "/setCookie", method = RequestMethod.GET)
public String setCookie(HttpServletResponse response) {
// 建立一個Cookie 物件
Cookie cookie = new Cookie("username", "kaijun");
// 設置過期時間,若無設置時間,其生命週期將持續到Session 過期為止
cookie.setMaxAge(7*24*60*60);
// 將Cookie 物件加入Response 中
response.addCookie(cookie);
return "add Cookie";
}
Spring 框架提供了@CookieValue
註釋來取得Cookie 的值,其參數 value
為Cookie 名稱,可使用參數 defaultValue
設定預設值,若沒有預設值也查無Cookie 名稱則會拋出IllegalStateException 例外。
@RequestMapping(value = "/getCookie", method = RequestMethod.GET)
public String getCookie(@CookieValue(value = "username") String username) {
return "Hello! " + username;
}
在實務上我們可能不只有一個Cookie,若要使用@CookieValue 一個一個取得會使得程式碼變得冗長,所以可以使用HttpServletRequest 的getCookies() 方法一次取得所有Cookie。
@RequestMapping(value = "/getCookies", method = RequestMethod.GET)
public String getCookies(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
return Arrays.stream(cookies)
.map(c -> c.getName() + "=" + c.getValue())
.collect(Collectors.joining(", "));
}
return "No cookies";
}
我們可以指定Cookie 僅能透過加密的HTTPS 連結發送Cookie 到伺服器,無法透過未加密的HTTP 連接傳送。
// 改寫上面setCookie 方法
@RequestMapping(value = "/setCookie", method = RequestMethod.GET)
public String setCookie(HttpServletResponse response) {
// 建立一個Cookie 物件
Cookie cookie = new Cookie("username", "kaijun");
// 設置過期時間,若無設置時間,其生命週期將持續到Session 過期為止
cookie.setMaxAge(7*24*60*60);
// 設置HTTPS 安全的Cookie
cookie.setSecure(true);
// 將Cookie 物件加入Response 中
response.addCookie(cookie);
return "add Cookie";
}
HttpOnly Cooke 是用於防止跨站點腳本攻擊(XSS),也就是設置了HttpOnly 的Cookie 無法透過JavaScript 的Document.cookieAPI 訪問伺服器。
// 再改寫上面setCookie 方法
@RequestMapping(value = "/setCookie", method = RequestMethod.GET)
public String setCookie(HttpServletResponse response) {
// 建立一個Cookie 物件
Cookie cookie = new Cookie("username", "kaijun");
// 設置過期時間,若無設置時間,其生命週期將持續到Session 過期為止
cookie.setMaxAge(7*24*60*60);
// 設置HTTPS 安全的Cookie
cookie.setSecure(true);
// 設置為不能被JS 訪問的Cookie
cookie.setHttpOnly(true);
// 將Cookie 物件加入Response 中
response.addCookie(cookie);
return "add Cookie";
}
到了最後不需要Cookie 值時,應該將其刪除以釋放記憶體資源,要刪除Cookie 需要將Cooke 值設為null 並將過期時間設置為0。
@RequestMapping(value = "/deleteCookie", method = RequestMethod.GET)
public String deleteCookie(HttpServletResponse response) {
// 將Cookie 值設置為null
Cookie cookie = new Cookie("username", null);
// 設置過期時間為0
cookie.setMaxAge(0);
// 將Cookie 物件加入Response 中
response.addCookie(cookie);
return "delete Cookie";
}
Cookie - 维基百科,自由的百科全书
如何在SpringBoot中使用Cookies