Skip to content

ES6 - Cookies

Cookies(通常译为“曲奇”或“小型文本文件”)是网站通过网页浏览器存储在用户计算机(或移动设备)上的少量数据。它们是维持无状态 HTTP 协议状态的基本机制,实现了会话管理(例如,保持用户登录状态)、个性化(例如,用户偏好设置)和用户行为跟踪等功能。

  1. 服务器发送 Cookie: 当用户访问一个网站时,服务器可以在其响应中发送一个 Set-Cookie HTTP 头部。该头部包含 Cookie 的名称、值和可选属性。
  2. 浏览器存储 Cookie: 如果浏览器设置允许,它会存储该 Cookie。
  3. 浏览器发送 Cookie: 在后续向同一域(以及路径,取决于 Cookie 属性)的请求中,浏览器会自动将相关的 Cookie 包含在发送给服务器的 Cookie HTTP 头部中。
  4. 服务器读取 Cookie: 服务器随后可以读取 Cookie 数据来识别用户、检索会话信息或自定义响应。
  • Name=Value: 存储在 Cookie 中的实际数据。这是唯一必需的部分。
  • Expires=date: 指定 Cookie 的过期日期和时间。如果省略,Cookie 将成为会话 Cookie,并在浏览器关闭时被删除。日期应为 UTC (GMT) 格式。
  • Max-Age=seconds: Expires 的替代方案,以秒为单位指定 Cookie 的生命周期。如果同时设置了 Expires 和 Max-Age,则 Max-Age 优先。
  • Domain=domain_name: Cookie 有效的域。如果未指定,默认为当前文档 URL 的主机(但不包括子域)。
  • Path=path: Cookie 有效的 URL 路径。如果未指定,默认为设置 Cookie 文档的当前路径。
  • Secure: 如果存在此属性,Cookie 将只通过 HTTPS 连接发送。
  • HttpOnly: 如果存在此属性,客户端 JavaScript (document.cookie) 将无法访问该 Cookie。这有助于减轻跨站脚本 (XSS) 攻击。
  • SameSite=Strict|Lax|None: 控制 Cookie 是否随跨站请求发送,提供对跨站请求伪造 (CSRF) 攻击的保护。None 要求设置 Secure 属性。

JavaScript 可以通过 document.cookie 属性与 Cookie 进行交互(那些未设置 HttpOnly 的 Cookie)。该属性允许您读取、创建、修改和删除与当前网页相关的 Cookie。

要创建或更新 Cookie,您需要向 document.cookie 属性分配一个字符串。字符串必须采用 name=value; expires=UTCString; path=/; SameSite=Lax 等格式。

重要编码注意事项:Cookie 的值不能包含分号、逗号或空白字符。在存储 Cookie 值之前,使用 encodeURIComponent() 进行编码至关重要;在读取时,使用 decodeURIComponent() 进行解码。旧的 escape() 和 unescape() 函数已被弃用,不应使用。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cookie Write Example</title>
<script>
function setUsernameCookie() {
const usernameInput = document.getElementById('username');
if (!usernameInput.value) {
alert('Please enter a username!');
return;
}
const username = encodeURIComponent(usernameInput.value);
const expiresDate = new Date();
expiresDate.setDate(expiresDate.getDate() + 7); // Expires in 7 days
document.cookie = `username=${username}; expires=${expiresDate.toUTCString()}; path=/; SameSite=Lax`;
document.getElementById('output').textContent = `Cookie set: username=${username}`;
}
</script>
</head>
<body>
<h2>Set User Preference</h2>
<label for="username">Username:</label>
<input type="text" id="username" name="username">
<button onclick="setUsernameCookie()">Set Cookie</button>
<p id="output"></p>
</body>
</html>

运行此 HTML 后,如果您输入用户名并点击“Set Cookie”,一个名为 ‘username’ 的 Cookie 将被存储在您的浏览器中。

document.cookie 返回一个字符串,其中包含当前页面可访问的所有 Cookie,它们之间用分号分隔(例如,name1=value1; name2=value2)。您需要解析此字符串以获取单个 Cookie 的值。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cookie Read Example</title>
<script>
function getCookie(name) {
const cookieString = document.cookie;
const cookies = cookieString.split(';');
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.startsWith(name + '=')) {
return decodeURIComponent(cookie.substring(name.length + 1));
}
}
return null; // Cookie not found
}
function displayUsername() {
const savedUsername = getCookie('username');
const outputElement = document.getElementById('savedUsername');
if (savedUsername) {
outputElement.textContent = `Welcome back, ${savedUsername}!`;
} else {
outputElement.textContent = 'No username cookie found.';
}
}
</script>
</head>
<body onload="displayUsername()">
<h2>User Greeting</h2>
<p id="savedUsername"></p>
<p><em>Try setting a username cookie from the 'Writing a Cookie' example first.</em></p>
</body>
</html>

当此页面加载时,它会尝试读取名为 ‘username’ 的 Cookie,如果找到则显示问候语。

如“写入 Cookie”示例所示,您可以使用带有 UTC 日期字符串的 expires 属性或带有秒数的 Max-Age 属性来设置过期日期。如果两者都没有设置,它就是一个会话 Cookie。

Section titled “示例:设置一个一小时后过期的 Cookie。”
const now = new Date();
now.setTime(now.getTime() + (60 * 60 * 1000)); // 1 hour in milliseconds
document.cookie = `myKey=myValue; expires=${now.toUTCString()}; path=/`;
// Or using Max-Age:
// 或者使用 Max-Age:
document.cookie = `myKey=myValue; Max-Age=3600; path=/`; // 3600 seconds = 1 hour

要删除 Cookie,您需要将其 expires 属性设置为一个过去的日期,或者将其 Max-Age 设置为 0 或负值。您还必须指定设置 Cookie 时使用的相同 path 和 domain 属性。

function deleteCookie(name) {
// Set expiry date to the past
// 将过期日期设置为过去
// Ensure path and domain match how the cookie was set. If not specified, they might default.
// 确保 path 和 domain 与设置 Cookie 时一致。如果未指定,可能会有默认值。
// For simplicity, assuming path is '/'
// 为简单起见,假设 path 为 '/'
document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';
// Or using Max-Age
// 或者使用 Max-Age
// document.cookie = name + '=; Max-Age=0; path=/';
console.log(`Cookie '${name}' deletion attempted.`);
}
// To use it:
// 如何使用:
// deleteCookie('username');
  • LocalStorage 和 SessionStorage: 对于仅存储在客户端且不需要随每个请求发送到服务器的数据,Web Storage API(localStorage 和 sessionStorage)提供了更现代、通常更方便的接口,且存储容量更大。
  • 安全性: - HttpOnly: 对于不需要被客户端 JavaScript 访问的 Cookie(例如,会话令牌),始终使用 HttpOnly。此属性由服务器设置。 - Secure: 使用 Secure 属性确保 Cookie 只通过 HTTPS 发送。此属性由服务器设置,或在为安全源创建 JS Cookie 时设置。 - SameSite: 使用 SameSite 属性(Strict、Lax 或 None)控制 Cookie 何时随跨域请求发送,有助于防止 CSRF 攻击。此属性由服务器设置,或在创建 JS Cookie 时设置。 - 数据敏感性: 避免在 Cookie 中存储敏感信息。如果必须存储,请确保其已加密并安全处理。
  • Cookie 大小: Cookie 的大小受限(通常每个 Cookie 约为 4KB),数量也受限(每个域约 20-50 个 Cookie,取决于浏览器)。
  • 性能: 随每个 HTTP 请求发送 Cookie 会增加开销,特别是当 Cookie 数量多或体积大时。考虑数据是否真的需要在每次请求时都发送到服务器。

有关 Cookie 及其属性的更详细信息,请查阅 MDN Web 文档: