JavaScript Cookies
什么是Cookies?
Cookies是存储在用户浏览器中的小型文本文件,用于在浏览器和服务器之间传递数据。它们是由服务器发送到浏览器的,然后浏览器会将其存储起来,并在后续请求中再次发送给服务器。
Cookies的主要用途包括:
- 会话管理:存储用户登录状态、会话ID等
- 个性化设置:存储用户偏好、主题选择等
- 追踪分析:记录用户行为、访问统计等
Cookies的特点
- 数据大小限制:通常为4KB左右
- 同源策略:只有同一个域名下的页面可以访问Cookies
- 自动发送:每次HTTP请求都会自动将Cookies发送到服务器
- 过期时间:可以设置过期时间,过期后自动删除
- 可以被禁用:用户可以在浏览器设置中禁用Cookies
- 明文存储:默认情况下,Cookies是明文存储的,不安全
Cookies的基本操作
1. 设置Cookies
使用document.cookie属性可以设置Cookies。设置Cookies的语法如下:
document.cookie = "key=value; expires=date; path=path; domain=domain; secure; httpOnly; sameSite=strict";- key=value:Cookies的键值对
- expires=date:Cookies的过期时间,格式为GMT时间
- path=path:Cookies的路径,默认为当前页面路径
- domain=domain:Cookies的域名,默认为当前域名
- secure:仅在HTTPS连接中发送Cookies
- httpOnly:Cookies只能通过HTTP请求发送,不能通过JavaScript访问
- sameSite:限制Cookies的发送条件,可选值为strict、lax或none
示例:设置Cookies
// 基本设置
document.cookie = "username=John";
// 设置过期时间(1小时后)
const now = new Date();
now.setTime(now.getTime() + 60 * 60 * 1000);
document.cookie = `username=John; expires=${now.toUTCString()}; path=/`;
// 设置安全Cookies(仅HTTPS)
document.cookie = "sessionId=12345; secure; sameSite=strict";2. 获取Cookies
使用document.cookie属性可以获取所有Cookies,返回一个字符串,包含所有Cookies的键值对,用分号分隔。
// 获取所有Cookies
const allCookies = document.cookie;
console.log(allCookies); // username=John; sessionId=12345
// 解析Cookies
function getCookie(name) {
const cookies = document.cookie.split('; ');
for (const cookie of cookies) {
const [cookieName, cookieValue] = cookie.split('=');
if (cookieName === name) {
return decodeURIComponent(cookieValue);
}
}
return null;
}
// 使用示例
const username = getCookie('username');
console.log(username); // John3. 更新Cookies
要更新Cookies,只需使用相同的键名设置新值即可。
// 更新Cookies
document.cookie = "username=Jane; path=/";4. 删除Cookies
要删除Cookies,只需将过期时间设置为过去的时间即可。
// 删除Cookies
function deleteCookie(name) {
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
}
// 使用示例
deleteCookie('username');Cookies的属性详解
1. expires属性
expires属性用于设置Cookies的过期时间。如果不设置expires属性,Cookies将在浏览器关闭后自动删除,称为会话Cookies。
// 会话Cookies(浏览器关闭后删除)
document.cookie = "sessionId=12345";
// 持久化Cookies(7天后过期)
const now = new Date();
now.setTime(now.getTime() + 7 * 24 * 60 * 60 * 1000);
document.cookie = `username=John; expires=${now.toUTCString()}; path=/`;2. max-age属性
max-age属性也用于设置Cookies的过期时间,单位为秒。与expires属性不同,max-age是相对于当前时间的秒数。
// 1小时后过期
document.cookie = "sessionId=12345; max-age=3600; path=/";
// 立即过期(删除Cookies)
document.cookie = "sessionId=12345; max-age=0; path=/";3. path属性
path属性用于设置Cookies的路径。只有当请求的路径匹配或包含Cookies的路径时,Cookies才会被发送。
// 只有在/mypath路径下的页面可以访问该Cookies
document.cookie = "username=John; path=/mypath";
// 所有路径下的页面都可以访问该Cookies
document.cookie = "username=John; path=/";4. domain属性
domain属性用于设置Cookies的域名。只有当请求的域名匹配Cookies的域名时,Cookies才会被发送。
// 只有example.com域名下的页面可以访问该Cookies
document.cookie = "username=John; domain=example.com; path=/";
// example.com及其所有子域名都可以访问该Cookies
document.cookie = "username=John; domain=.example.com; path=/";5. secure属性
secure属性用于指定Cookies仅在HTTPS连接中发送。使用secure属性可以提高Cookies的安全性,防止在HTTP连接中被窃取。
// 仅在HTTPS连接中发送
document.cookie = "sessionId=12345; secure; path=/";6. httpOnly属性
httpOnly属性用于指定Cookies只能通过HTTP请求发送,不能通过JavaScript访问。使用httpOnly属性可以防止跨站脚本攻击(XSS)窃取Cookies。
注意:httpOnly属性只能在服务器端设置,不能通过JavaScript设置。
7. sameSite属性
sameSite属性用于限制Cookies的发送条件,防止跨站请求伪造攻击(CSRF)。可选值包括:
- strict:仅在同一站点请求中发送Cookies
- lax:允许在GET请求中发送Cookies,但不允许在POST请求中发送
- none:允许在所有请求中发送Cookies,但必须同时设置
secure属性
// 严格模式:仅在同一站点请求中发送
document.cookie = "sessionId=12345; sameSite=strict; secure; path=/";
// 宽松模式:允许在GET请求中发送
document.cookie = "sessionId=12345; sameSite=lax; path=/";
// 无限制:允许在所有请求中发送,但必须设置secure
document.cookie = "sessionId=12345; sameSite=none; secure; path=/";Cookies的使用场景
1. 会话管理
// 保存用户登录状态
function saveLoginState(username, isLoggedIn) {
const now = new Date();
now.setTime(now.getTime() + 24 * 60 * 60 * 1000); // 1天后过期
document.cookie = `isLoggedIn=${isLoggedIn}; expires=${now.toUTCString()}; path=/`;
document.cookie = `username=${encodeURIComponent(username)}; expires=${now.toUTCString()}; path=/`;
}
// 获取用户登录状态
function getLoginState() {
const isLoggedIn = getCookie('isLoggedIn') === 'true';
const username = decodeURIComponent(getCookie('username') || '');
return { isLoggedIn, username };
}
// 检查用户登录状态
const loginState = getLoginState();
if (loginState.isLoggedIn) {
console.log(`欢迎回来,${loginState.username}!`);
} else {
console.log('请登录!');
}2. 个性化设置
// 保存用户主题偏好
function saveThemePreference(theme) {
const now = new Date();
now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000); // 1年后过期
document.cookie = `theme=${theme}; expires=${now.toUTCString()}; path=/`;
}
// 获取用户主题偏好
function getThemePreference() {
return getCookie('theme') || 'light';
}
// 应用主题偏好
const theme = getThemePreference();
document.body.className = `theme-${theme}`;3. 追踪分析
// 保存用户访问信息
function saveVisitInfo() {
const visitCount = parseInt(getCookie('visitCount') || '0') + 1;
const now = new Date();
now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000); // 1年后过期
document.cookie = `visitCount=${visitCount}; expires=${now.toUTCString()}; path=/`;
document.cookie = `lastVisit=${now.toUTCString()}; expires=${now.toUTCString()}; path=/`;
}
// 页面加载时调用
saveVisitInfo();
// 显示访问信息
const visitCount = getCookie('visitCount');
const lastVisit = getCookie('lastVisit');
console.log(`您是第${visitCount}次访问本网站,上次访问时间是${lastVisit}`);Cookies的安全问题
1. 跨站脚本攻击(XSS)
XSS攻击是指攻击者通过注入恶意脚本,窃取用户的Cookies等敏感信息。为了防止XSS攻击,可以使用以下措施:
- 设置
httpOnly属性,防止JavaScript访问Cookies - 对用户输入进行过滤和转义
- 使用内容安全策略(CSP)
2. 跨站请求伪造(CSRF)
CSRF攻击是指攻击者利用用户已登录的身份,诱使用户访问恶意网站,执行未授权操作。为了防止CSRF攻击,可以使用以下措施:
- 设置
sameSite属性,限制Cookies的发送条件 - 使用CSRF令牌
- 验证Referer头
3. 会话固定攻击
会话固定攻击是指攻击者固定用户的会话ID,然后诱导用户使用该会话ID登录,从而获取用户的身份。为了防止会话固定攻击,可以使用以下措施:
- 用户登录后重新生成会话ID
- 设置合理的会话过期时间
Cookies与其他存储方式的比较
| 特性 | Cookies | LocalStorage | SessionStorage | IndexedDB |
|---|---|---|---|---|
| 数据大小 | 约4KB | 约5MB | 约5MB | 无限制 |
| 自动发送 | 是 | 否 | 否 | 否 |
| 过期时间 | 可设置 | 持久化 | 会话级 | 持久化 |
| 同源策略 | 是 | 是 | 是 | 是 |
| 服务器访问 | 是 | 否 | 否 | 否 |
| 适用场景 | 会话管理、认证 | 长期存储、用户偏好 | 临时数据、表单缓存 | 大量结构化数据 |
Cookies的最佳实践
- 使用HTTPS:在生产环境中,始终使用HTTPS协议,并设置
secure属性 - 设置合理的过期时间:根据数据的重要性和使用频率,设置合理的过期时间
- 使用httpOnly属性:对于敏感数据,如会话ID,设置
httpOnly属性 - 使用sameSite属性:设置
sameSite属性,防止CSRF攻击 - 加密敏感数据:对于敏感数据,如用户信息,使用加密算法加密后再存储
- 最小化数据大小:只存储必要的数据,避免存储大量数据
- 使用合理的路径和域名:根据实际需求,设置合理的
path和domain属性 - 定期清理过期数据:定期检查并清理过期的Cookies
- 提供Cookies政策:在网站上提供Cookies政策,告知用户Cookies的使用情况
- 尊重用户选择:允许用户选择是否接受Cookies,特别是用于追踪分析的Cookies
示例:完整的Cookies管理函数
// Cookies管理工具
const CookieManager = {
// 设置Cookies
set: function(name, value, options = {}) {
let cookieString = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
if (options.expires) {
const expires = new Date(options.expires);
cookieString += `; expires=${expires.toUTCString()}`;
}
if (options.maxAge) {
cookieString += `; max-age=${options.maxAge}`;
}
if (options.path) {
cookieString += `; path=${options.path}`;
}
if (options.domain) {
cookieString += `; domain=${options.domain}`;
}
if (options.secure) {
cookieString += '; secure';
}
if (options.sameSite) {
cookieString += `; sameSite=${options.sameSite}`;
}
document.cookie = cookieString;
},
// 获取Cookies
get: function(name) {
const cookies = document.cookie.split('; ');
for (const cookie of cookies) {
const [cookieName, cookieValue] = cookie.split('=');
if (decodeURIComponent(cookieName) === name) {
return decodeURIComponent(cookieValue);
}
}
return null;
},
// 删除Cookies
delete: function(name, options = {}) {
this.set(name, '', {
...options,
maxAge: 0
});
},
// 检查Cookies是否存在
has: function(name) {
return this.get(name) !== null;
},
// 清除所有Cookies
clear: function() {
const cookies = document.cookie.split('; ');
for (const cookie of cookies) {
const [cookieName] = cookie.split('=');
this.delete(decodeURIComponent(cookieName));
}
}
};
// 使用示例
CookieManager.set('username', 'John', {
expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
path: '/',
secure: true,
sameSite: 'strict'
});
const username = CookieManager.get('username');
console.log(username); // John
CookieManager.delete('username');总结
Cookies是一种重要的客户端存储方式,用于在浏览器和服务器之间传递数据。它们具有大小限制、自动发送、过期时间等特点,适用于会话管理、个性化设置和追踪分析等场景。
在使用Cookies时,需要注意安全性问题,如XSS攻击、CSRF攻击和会话固定攻击等。通过设置httpOnly、secure和sameSite等属性,可以提高Cookies的安全性。
与其他存储方式相比,Cookies的主要优势是可以自动发送到服务器,适用于需要在服务器和浏览器之间传递数据的场景。但它们的数据大小限制较小,不适合存储大量数据。
在实际开发中,应根据具体需求选择合适的存储方式,并遵循最佳实践,确保数据的安全性和可靠性。
练习
实现一个Cookies管理工具,包含设置、获取、删除和清除Cookies的功能。
使用Cookies实现用户登录状态管理,包括登录、注销和状态检查。
使用Cookies实现用户主题偏好设置,支持浅色主题和深色主题切换。
比较Cookies、LocalStorage和SessionStorage的区别,并说明它们的适用场景。
实现一个简单的访问计数器,使用Cookies记录用户访问次数和上次访问时间。