cookie通俗讲解
# Cookie 在浏览器中的存储
浏览器中的 cookie 是一种用于存储小型数据的机制,通常用于会话管理、身份验证、个性化设置以及跟踪用户活动。具体来说,浏览器会将 cookie 存储在本地文件系统中,并在每次访问相同网站时自动附加相应的 cookie 数据。浏览器存储 cookie 的方式包括以下几个关键点:
存储位置:
- Cookie 通常存储在浏览器的特定文件夹中。不同的浏览器有不同的存储路径。例如,在 Chrome 中,cookie 存储在
LocalStorage
或浏览器的 SQLite 数据库中。 - 浏览器会为每个域名创建独立的 cookie 存储空间,保证不同网站的 cookie 互不干扰。
- Cookie 通常存储在浏览器的特定文件夹中。不同的浏览器有不同的存储路径。例如,在 Chrome 中,cookie 存储在
存储内容:
- 每个 cookie 由几个部分组成:名称、值、域名、路径、过期时间、Secure 属性、SameSite 属性等。
- 名称和值:这是 cookie 的主要数据部分,通常由服务器在响应头中通过
Set-Cookie
指令设置。 - 域名与路径:指定了 cookie 适用的域名和路径。只有匹配的域名和路径才能访问到该 cookie。
- 过期时间:如果没有设置,cookie 为会话 cookie,只在浏览器打开期间有效。一旦浏览器关闭,cookie 就会被删除。
- Secure:指定 cookie 只能通过 HTTPS 协议传输。
- SameSite:这个属性用于防止跨站请求伪造攻击 (CSRF),控制 cookie 是否仅在同站请求中发送。
- 名称和值:这是 cookie 的主要数据部分,通常由服务器在响应头中通过
- 每个 cookie 由几个部分组成:名称、值、域名、路径、过期时间、Secure 属性、SameSite 属性等。
如何存储和发送:
- 当你访问某个网站时,浏览器会根据域名匹配存储在本地的 cookie 并将其附加到请求中,发送到相应的服务器。服务器会使用这些 cookie 来识别客户端,执行相应的会话管理或身份验证操作。
# 为什么 curl
直接带上 cookie 的值就可以
curl
是一个命令行工具,它本身不会像浏览器一样自动管理 cookie。相反,curl
是通过将 cookie 的信息手动传递来模拟请求中携带 cookie 的行为。
# 工作原理:
模拟请求:当你使用
curl
发送请求时,你可以通过-b
或--cookie
选项显式地提供 cookie 数据。例如:curl -b "name=value" https://example.com
1这里的
"name=value"
就是一个 cookie 数据,它将会被附加到请求头中,模拟真实浏览器的行为。手动提供 cookie:
- 在浏览器中,cookie 会自动管理和存储,浏览器会根据网站的设置自动带上正确的 cookie。
- 在
curl
中,由于没有内建的 cookie 存储机制,所以你需要手动传递 cookie 数据。通过-b
或--cookie
选项,你可以指定 cookie 的内容,curl
会将其作为请求头的一部分发送出去。
与浏览器的区别:
- 在浏览器中,cookie 是由浏览器自动管理的,包括设置、存储和发送。当你访问一个网站时,浏览器会自动附加符合条件的 cookie。
- 在
curl
中,你需要手动指定哪些 cookie 应该被带上,因为curl
本身不管理 cookie。如果你已经有一个有效的 cookie 值(可能是从浏览器或其他来源获得),你可以通过curl
将其直接附加到请求中。
# 例如:
curl -b "session_id=12345; logged_in=true" https://example.com
这条命令会将 session_id
和 logged_in
的 cookie 数据附加到请求头中,向服务器发送请求,服务器将根据这些 cookie 信息进行处理。
# 如果不使用 cookie 来存储和管理数据,依然有一些替代方式可以用来管理用户的会话、存储信息和个性化设置。以下是几种常见的替代技术:
# 1. LocalStorage
- 功能:
localStorage
是一种可以在浏览器中存储数据的机制,数据是以键值对形式保存在浏览器中,且数据不会过期,直到手动删除。与 cookie 不同,localStorage
存储的数据不随每个 HTTP 请求一起发送,具有更高的存储容量(通常为 5MB 或更多)。 - 特点:
- 永久存储,除非手动清除。
- 只在客户端使用,不会随请求发送给服务器。
- 每个网站都有独立的存储空间。
- 使用场景:适合存储长期有效的数据,如用户设置、主题偏好等。
- 示例代码:
// 存储数据 localStorage.setItem('username', 'JohnDoe'); // 获取数据 const username = localStorage.getItem('username'); // 删除数据 localStorage.removeItem('username');
1
2
3
4
5
6
7
8
# 2. SessionStorage
- 功能:
sessionStorage
与localStorage
类似,但数据仅在浏览器的会话期间有效。当浏览器窗口或标签页关闭时,存储的数据会被清除。数据也是存储在键值对中,不会随 HTTP 请求发送。 - 特点:
- 数据在浏览器会话期间有效。
- 数据仅限于当前浏览器窗口或标签页,不能跨标签页共享。
- 使用场景:适用于存储临时会话数据,如在单页应用中保存用户输入的数据,或在多步骤表单中暂存数据。
- 示例代码:
// 存储数据 sessionStorage.setItem('sessionID', 'abc123'); // 获取数据 const sessionID = sessionStorage.getItem('sessionID'); // 删除数据 sessionStorage.removeItem('sessionID');
1
2
3
4
5
6
7
8
# 3. IndexedDB
- 功能:
IndexedDB
是一种浏览器中的低级别 API,用于存储大量结构化数据。它支持事务,并且能够存储复杂的数据类型,如文件、二进制数据等。IndexedDB
是异步的,适合需要存储大量数据的应用。 - 特点:
- 存储容量比
localStorage
更大,可以存储大量数据。 - 支持键值对、对象存储和索引的结构化数据。
- 异步操作,适用于更复杂的应用。
- 存储容量比
- 使用场景:适用于需要存储大量数据的应用,例如离线应用、富客户端应用、游戏存档等。
- 示例代码:
const request = indexedDB.open('MyDatabase', 1); request.onsuccess = function(event) { const db = event.target.result; const transaction = db.transaction(['users'], 'readwrite'); const objectStore = transaction.objectStore('users'); objectStore.add({ id: 1, name: 'John Doe' }); };
1
2
3
4
5
6
7
8
# 4. Cache API (Service Worker)
功能:通过 Service Worker,你可以使用 Cache API 来缓存网站的资源,如 HTML 文件、图片、JavaScript 文件等。它主要用于离线应用,将静态资源保存在浏览器中,支持网页在没有网络连接时依然可以运行。
特点:
- 用于缓存资源而非普通数据。
- 可以实现离线体验。
- 异步操作。
使用场景:适用于需要离线支持的应用,或需要缓存大量静态资源的应用。
示例代码:
if ('caches' in window) { caches.open('my-cache').then(function(cache) { cache.addAll([ '/index.html', '/style.css', '/script.js' ]); }); }
1
2
3
4
5
6
7
8
9
# 总结
浏览器中可以使用多种方式来管理和存储数据,而不仅仅依赖于 cookie。主要的替代方案包括 localStorage
、sessionStorage
、IndexedDB
等。每种存储方式都有不同的特性和使用场景,可以根据应用需求选择合适的方式进行数据管理。
localStorage
:适合长期存储不随请求发送的数据。sessionStorage
:适合临时存储,仅限于会话期间。IndexedDB
:适合存储大量结构化数据,支持复杂操作。- 服务器端存储:适合存储需要安全性和跨设备同步的数据。
# cookie
、localStorage
和 sessionStorage
是浏览器中三种常见的存储方式
# 1. Cookie
- 存储位置:客户端浏览器,且每次 HTTP 请求都会将 cookie 附带到请求头中发送给服务器。
- 大小限制:通常每个 cookie 的大小限制在 4KB 左右,不同浏览器和域名限制可能有所差异。
- 数据类型:只能存储 字符串 类型数据,非字符串数据(如对象或数组)需要先序列化为字符串(例如 JSON 格式)。
- 生命周期:
- 可设置过期时间(
Expires
或Max-Age
),到期后自动失效。 - 如果未设置过期时间,cookie 默认是会话级的(即当浏览器关闭时删除)。
- 可设置过期时间(
- 安全性:
- 可设置
HttpOnly
标记,防止 JavaScript 访问。 - 可设置
Secure
标记,确保 cookie 仅在 HTTPS 连接下发送。
- 可设置
- 典型应用场景:用于服务器端会话管理(如登录状态),记录用户偏好设置等。
- 优缺点:
- 优点:支持跨请求传输,适用于会话管理。
- 缺点:容量小,每次请求都会携带,增加网络流量。
# 2. localStorage
- 存储位置:客户端浏览器,仅限在同一浏览器内使用,不会随 HTTP 请求发送到服务器。
- 大小限制:一般 5MB 左右,不同浏览器可能有些差异。
- 数据类型:只能存储 字符串 类型,其他数据(如对象、数组)需要转换为字符串(例如 JSON 格式)。
- 生命周期:永久存储,数据在浏览器关闭后依然存在,除非手动清除。
- 安全性:无内置安全机制,可通过 JavaScript 轻松访问,适用于存储非敏感信息。
- 典型应用场景:存储用户设置、主题偏好等长期存在的数据。
- 优缺点:
- 优点:容量大,适合长期存储。
- 缺点:缺少安全性,不适合存储敏感信息。
# 3. sessionStorage
- 存储位置:客户端浏览器,仅限于同一窗口或标签页中使用,不会随 HTTP 请求发送到服务器。
- 大小限制:一般也是 5MB 左右,和
localStorage
类似。 - 数据类型:仅支持 字符串 类型,复杂数据需要转换为字符串格式(如 JSON)。
- 生命周期:会话级别,数据在标签页或窗口关闭后即删除。
- 安全性:与
localStorage
相似,缺少内置安全保护。 - 典型应用场景:适用于存储临时数据,如表单数据、会话状态等。
- 优缺点:
- 优点:会话独立,不会跨标签页或窗口共享。
- 缺点:缺少安全性,数据易失效。
# 综合对比
特性 | Cookie | localStorage | sessionStorage |
---|---|---|---|
存储位置 | 浏览器与服务器共享 | 仅在浏览器端 | 仅在浏览器端 |
大小限制 | 约 4KB | 约 5MB | 约 5MB |
数据类型 | 字符串 | 字符串 | 字符串 |
生命周期 | 可设定过期时间 | 永久存储 | 会话结束时清除 |
数据传输 | 每次请求自动发送 | 不随请求发送 | 不随请求发送 |
安全性 | 可通过标记增强安全性 | 缺少安全机制 | 缺少安全机制 |
应用场景 | 会话管理、用户偏好 | 长期数据存储 | 临时数据存储 |
# 总结
- cookie 更适合服务端会话管理等需要在客户端与服务器端共享数据的场景。
- localStorage 适合长期保存、无需随请求传递的大容量数据。
- sessionStorage 适用于会话级、页面独立的临时数据存储。
# IndexedDB
基础
# 使用场景
- 离线 Web 应用:可以在离线状态下保存用户数据,并在恢复网络连接后同步。适合应用包括离线笔记、聊天记录缓存等。
- 大型数据存储:可处理大量数据和结构化对象数据,例如电子商务应用中缓存商品数据、地图应用中缓存地理信息。
- 本地持久化存储:适合对用户行为进行持久化存储,用于追踪用户进度、偏好设置等,如在线学习平台的学习记录。
- 游戏存储:在浏览器中运行的游戏可利用 IndexedDB 存储用户成就、进度等数据,提升体验。
- 文件存储和缓存:可以将文件缓存下来,减少网络请求频次,如 Web 应用中缓存图片、音频、视频文件等。
# 常见的 IndexedDB 使用命令
IndexedDB
操作都是异步的,通常通过 request
对象来监听事件。以下是一些常用命令和代码示例:
# 1. 创建或打开数据库
- 使用
indexedDB.open
方法创建或打开数据库。 - 创建或升级数据库版本时会触发
onupgradeneeded
事件,用于定义数据表结构。
const request = indexedDB.open("myDatabase", 1);
request.onupgradeneeded = (event) => {
const db = event.target.result;
// 创建一个对象存储(类似表格)
if (!db.objectStoreNames.contains("myObjectStore")) {
db.createObjectStore("myObjectStore", { keyPath: "id" });
}
};
request.onsuccess = (event) => {
const db = event.target.result;
console.log("Database opened successfully");
};
request.onerror = (event) => {
console.error("Error opening database:", event.target.error);
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 2. 添加数据
- 使用
transaction
方法开启事务,并使用objectStore.put()
添加数据。
const transaction = db.transaction("myObjectStore", "readwrite");
const objectStore = transaction.objectStore("myObjectStore");
const data = { id: 1, name: "John Doe", age: 30 };
const addRequest = objectStore.add(data);
addRequest.onsuccess = () => console.log("Data added successfully");
addRequest.onerror = (event) => console.error("Error adding data:", event.target.error);
2
3
4
5
6
7
8
# 3. 读取数据
- 使用
objectStore.get()
方法通过主键读取数据。 - 也可以使用
openCursor
遍历所有数据。
const getRequest = objectStore.get(1); // 获取主键为1的记录
getRequest.onsuccess = (event) => {
console.log("Data fetched:", event.target.result);
};
getRequest.onerror = (event) => console.error("Error fetching data:", event.target.error);
2
3
4
5
6
7
- 遍历所有数据:
objectStore.openCursor().onsuccess = (event) => {
const cursor = event.target.result;
if (cursor) {
console.log("Data:", cursor.value);
cursor.continue(); // 继续到下一个记录
} else {
console.log("No more entries!");
}
};
2
3
4
5
6
7
8
9
# 4. 更新数据
- 使用
objectStore.put()
更新数据。若主键存在,则更新该记录;若不存在,则添加新记录。
const updateData = { id: 1, name: "Jane Doe", age: 28 };
const updateRequest = objectStore.put(updateData);
updateRequest.onsuccess = () => console.log("Data updated successfully");
updateRequest.onerror = (event) => console.error("Error updating data:", event.target.error);
2
3
4
5
# 5. 删除数据
- 使用
objectStore.delete()
方法删除指定主键的数据。
const deleteRequest = objectStore.delete(1); // 删除主键为1的记录
deleteRequest.onsuccess = () => console.log("Data deleted successfully");
deleteRequest.onerror = (event) => console.error("Error deleting data:", event.target.error);
2
3
4
# 6. 删除数据库
- 使用
indexedDB.deleteDatabase()
删除整个数据库。
const deleteDbRequest = indexedDB.deleteDatabase("myDatabase");
deleteDbRequest.onsuccess = () => console.log("Database deleted successfully");
deleteDbRequest.onerror = (event) => console.error("Error deleting database:", event.target.error);
2
3
4
# 7. 处理错误
- IndexedDB 操作的错误需要通过事件捕获,通常在
onerror
事件中处理。 - 错误的原因可能包括主键冲突、数据库未打开等。
# 总结
IndexedDB
提供了高效的离线存储解决方案,非常适合存储较大且结构化的数据。掌握了上述常用命令,能够满足绝大部分 Web 应用的离线存储需求。
# 在 PHP 和 JavaScript 中管理 Cookie 的方式有所不同,各自提供了操作 Cookie 的方法。
# 1. PHP 中管理 Cookie
# 1.1 设置 Cookie
在 PHP 中使用 setcookie()
函数来设置 Cookie。设置时可以指定 Cookie 的名称、值、过期时间、路径、域、是否仅允许 HTTPS 访问,以及是否仅通过 HTTP 访问(不可用 JavaScript)。
// 设置一个名为 "user" 的 Cookie,有效期为 1 天
setcookie("user", "Lorena", time() + 86400, "/");
2
解释:
"user"
:Cookie 的名称。"Lorena"
:Cookie 的值。time() + 86400
:过期时间,当前时间戳加上一天的秒数(86400)。"/"
:路径,表示 Cookie 在整个网站下可用。
# 1.2 获取 Cookie
PHP 中可以通过 $_COOKIE
超全局数组来访问已经设置的 Cookie。
if (isset($_COOKIE["user"])) {
echo "User is " . $_COOKIE["user"];
} else {
echo "User cookie is not set.";
}
2
3
4
5
解释:
$_COOKIE["user"]
:访问名为"user"
的 Cookie 值。isset()
:检查指定的 Cookie 是否已设置。
# 1.3 删除 Cookie
删除 Cookie 时,需要使用 setcookie()
函数将过期时间设置为过去的时间。例如,将过期时间设置为 time() - 3600
即可删除 Cookie。
setcookie("user", "", time() - 3600, "/");
解释:
- 将过期时间设置为过去的时间,让浏览器自动删除该 Cookie。
# 2. JavaScript 中管理 Cookie
JavaScript 没有内置的专门 API 来管理 Cookie,需要通过 document.cookie
进行操作。
# 2.1 设置 Cookie
在 JavaScript 中,设置 Cookie 时通过直接给 document.cookie
赋值来实现。可以使用 expires
属性来指定过期时间,还可以设置 path
、domain
、secure
和 HttpOnly
属性。
// 设置一个名为 "user" 的 Cookie,有效期为 1 天
document.cookie = "user=Lorena; expires=" + new Date(new Date().getTime() + 86400000).toUTCString() + "; path=/";
2
解释:
"user=Lorena"
:设置 Cookie 的名称和值。expires
:设置过期时间为 1 天后。path=/
:Cookie 在整个网站下可用。
# 2.2 获取 Cookie
在 JavaScript 中,document.cookie
返回当前文档的所有 Cookie,格式是一个字符串,多个 Cookie 使用 ;
分隔。因此,需要解析字符串来获取特定的 Cookie。
function getCookie(name) {
const cookies = document.cookie.split("; ");
for (let cookie of cookies) {
const [key, value] = cookie.split("=");
if (key === name) {
return value;
}
}
return null;
}
// 获取名为 "user" 的 Cookie 值
console.log(getCookie("user"));
2
3
4
5
6
7
8
9
10
11
12
13
解释:
document.cookie.split("; ")
:将 Cookie 字符串拆分成每个独立的 Cookie。key === name
:判断当前 Cookie 是否为需要获取的名称。
# 2.3 删除 Cookie
在 JavaScript 中删除 Cookie 需要设置相同的名称、路径、域等,并将 expires
属性设置为过去的时间。
document.cookie = "user=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
解释:
- 设置
expires
为过去的时间(如 1970 年),让浏览器自动删除该 Cookie。
# 对比总结
特性 | PHP | JavaScript |
---|---|---|
设置 Cookie | 使用 setcookie() 函数 | 直接设置 document.cookie |
获取 Cookie | 使用 $_COOKIE 超全局数组 | 解析 document.cookie 字符串 |
删除 Cookie | 通过 setcookie() 设置过去时间 | 设置 expires 为过去的时间 |
作用 | 服务器端管理,适用于动态响应数据 | 客户端管理,适合前端交互和显示 |
# 注意事项
- 安全性:对于敏感信息,建议通过 PHP 设置
HttpOnly
标志,这样客户端 JavaScript 无法访问。 - 过期时间:PHP 和 JavaScript 都可以通过过期时间控制 Cookie 生命周期,临时性 Cookie(会话期)不需要设置
expires
。 - 大小限制:通常,单个 Cookie 大小限制约为 4 KB,且总数限制约为 20 个到 50 个(取决于浏览器)。