Cookie 是伺服器儲存在客戶端瀏覽器的小型文字資料,用於識別用戶、記住偏好設定、追蹤行為等。JSP 透過 response.addCookie() 寫入、request.getCookies() 讀取。
<%@ page import="javax.servlet.http.Cookie, java.net.URLEncoder" %>
<%
// 1. 建立 Cookie (名稱、值皆為 String)
Cookie userCookie = new Cookie("username", URLEncoder.encode("王小明", "UTF-8"));
Cookie langCookie = new Cookie("lang", "zh-TW");
// 2. 設定屬性
userCookie.setMaxAge(60 * 60 * 24 * 30); // 30 天 (秒),負數 = 瀏覽器關閉即刪除 (Session Cookie)
userCookie.setPath("/"); // 整個網域有效
userCookie.setDomain("example.com"); // 可跨子網域 (需同主網域)
userCookie.setSecure(true); // 僅 HTTPS 傳送
userCookie.setHttpOnly(true); // 防止 JavaScript 存取 (XSS 防護)
// userCookie.setComment("用戶名稱"); // 說明 (較少用)
// 3. 寫入回應
response.addCookie(userCookie);
response.addCookie(langCookie);
%>
| 方法 | 說明 |
|---|---|
setMaxAge(秒) | 存活時間:正數=持久、0=立即刪除、負數=Session Cookie |
setPath(String) | Cookie 生效路徑,預設為當前 Servlet 路徑 |
setDomain(String) | 跨子網域共享,如 .example.com |
setSecure(boolean) | 僅 HTTPS 傳送 |
setHttpOnly(boolean) | 禁止 JS 讀取 (document.cookie 不可見) |
Cookie 值不支援中文、空格、特殊符號,必須編碼:
// 寫入時編碼
String encoded = URLEncoder.encode("中文值", "UTF-8");
Cookie c = new Cookie("key", encoded);
// 讀取時解碼
String decoded = URLDecoder.decode(cookie.getValue(), "UTF-8");
<%@ page import="javax.servlet.http.Cookie, java.net.URLDecoder" %>
<%
Cookie[] cookies = request.getCookies();
String username = null, lang = null;
if (cookies != null) {
for (Cookie c : cookies) {
switch (c.getName()) {
case "username":
username = URLDecoder.decode(c.getValue(), "UTF-8");
break;
case "lang":
lang = c.getValue();
break;
}
}
}
%>
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>讀取 Cookie</title></head>
<body>
<h2>Cookie 內容</h2>
<p>用戶:<%= username != null ? username : "未設定" %></p>
<p>語言:<%= lang != null ? lang : "預設" %></p>
</body></html>
無直接刪除 API,需建立同名 Cookie、設定 MaxAge=0、相同 Path/Domain、加入回應:
Cookie c = new Cookie("username", "");
c.setMaxAge(0);
c.setPath("/"); // 必須與建立時相同
// c.setDomain("example.com"); // 若建立時設定了 domain
response.addCookie(c);
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ page import="javax.servlet.http.Cookie, java.net.URLDecoder" %>
<%
String savedUser = "";
Cookie[] cs = request.getCookies();
if (cs != null) for (Cookie c : cs) if ("rememberUser".equals(c.getName())) {
savedUser = URLDecoder.decode(c.getValue(), "UTF-8");
break;
}
%>
<form action="doLogin.jsp" method="post">
帳號:<input type="text" name="username" value="<%= savedUser %>"><br>
密碼:<input type="password" name="password"><br>
<label><input type="checkbox" name="remember" value="true"> 記住我</label><br>
<button type="submit">登入</button>
</form>
<%@ page import="javax.servlet.http.Cookie, java.net.URLEncoder" %>
<%
String user = request.getParameter("username");
String pass = request.getParameter("password");
boolean remember = "true".equals(request.getParameter("remember"));
// 簡易驗證 (實務查資料庫)
if ("admin".equals(user) && "1234".equals(pass)) {
session.setAttribute("loginUser", user);
if (remember) {
Cookie c = new Cookie("rememberUser", URLEncoder.encode(user, "UTF-8"));
c.setMaxAge(60*60*24*14); // 14 天
c.setPath("/");
c.setHttpOnly(true);
response.addCookie(c);
} else {
// 取消記住
Cookie c = new Cookie("rememberUser", "");
c.setMaxAge(0);
c.setPath("/");
response.addCookie(c);
}
response.sendRedirect("welcome.jsp");
} else {
out.println("帳號密碼錯誤 <a href='login.jsp'>重試</a>");
}
%>
| 特性 | Cookie | Session |
|---|---|---|
| 儲存位置 | 客戶端瀏覽器 | 伺服器記憶體/Redis/資料庫 |
| 容量限制 | 單一 Cookie 4KB,每域 ~20-50 個 | 視伺服器記憶體而定 |
| 安全性 | 可被竄改、攔截、XSS 竊取 | 資料不暴露給客戶端,較安全 |
| 生命週期 | 可長期持久化 | 通常短期 (逾時自動銷毀) |
| 適用場景 | 記住偏好、追蹤、Remember Me | 登入狀態、購物車、敏感資料 |
SameSite=Strict (防 CSRF) 或 Lax (平衡體驗)