什么是 cookie ?
模块 | 界说 |
---|---|
了解 | Cookie 是一小块 数据(服务端发送给阅读器)。阅读器存储 Cookie 用于与服务端之间传输数据。 |
效果 | 坚持会话(登录状况)-个性化设置(主题)-阅读器行为追寻(分析用户行为) |
品种 |
会话 (阅读器封闭就删去)、持久(登录状况等)、第一方 (本网站)/第三方 (其他域名)、安全 (HTTPS、httpOnly、SmaeSite Cookie) |
如何运用 Cookie
留意: Cookie 运用要安全,通常需求 加密。
cookie 设置特点
称号 | 类型 | 描绘 |
---|---|---|
Name | String | Cookie 的称号,用于标识 Cookie。 |
Value | String | Cookie 的值,包括该 Cookie 的详细信息。 |
Expires/Max-Age | Date/Number | Cookie 的过期时刻,能够经过设置 Expires 或者 Max-Age 特点来指定。假如不设置,那么该 Cookie 将在阅读器封闭时主动删去。 |
Domain | String | Cookie 所属的域名。假如不指定,那么该 Cookie 将仅适用于设置它的域名。 |
Path | String | Cookie 所在的途径。假如不指定,那么该 Cookie 将仅适用于设置它的途径。 |
Secure | Boolean | 一个布尔值,表示是否仅在运用 HTTPS 协议时发送 Cookie。假如设置为 true ,则该 Cookie 仅适用于 HTTPS 协议。 |
HttpOnly | Boolean | 一个布尔值,表示是否允许客户端经过 JavaScript 拜访该 Cookie。假如设置为 true ,则该 Cookie 仅适用于 HTTP 协议,并且无法经过 JavaScript 拜访。 |
阅读器读取 Cookie 和解析 Cookie
览器供给了一个名为 document.cookie
的 API,能够用于读取和设置 Cookie。
const cookies = document.cookie.split("; ");
cookies.forEach((cookie) => {
const [name, value] = cookie.split("=");
console.log(`${name}=${value}`);
});
以 Node.js 为比如运用 Cookie
import http from 'node:http'
const server = http.createServer((req, res) => { {
// 在呼应头中设置 Cookie
const server = http.createServer((req, res) => { // 服务器呼应恳求的逻辑代码 });
// 从恳求头中读取 Cookie:
const cookie = req.headers.cookie;
// ...
});
server.listen(3000, () => { console.log('Server is running on port 3000'); });
当然假如你运用 express
等结构会供给愈加简单的操作 cookie 办法:cookie-parser。
cookie 的约束
约束/特点 | 描绘 | 格式/可选值 |
---|---|---|
巨细约束 | 每个 Cookie 的巨细 | 4KB 以内 |
数量约束 | 每个域名下 Cookie 的数量 | 50 个以内 |
安全约束 | Secure |
true/false |
安全约束 | HttpOnly |
true/false |
有用期约束 | Expires |
格式:Wdy, DD-Mon-YYYY HH:MM:SS GMT |
有用期约束 | Max-Age |
单位:秒 |
途径约束 | Path |
Cookie 的途径 |
cookie 运用场景
运用场景 | 描绘 |
---|---|
身份验证 | 经过在用户登录时创立 Cookie 来标识用户身份,运用户能够在会话期间坚持登录状况。 |
记住暗码 | 创立一个包括用户名和暗码的 Cookie,使得用户能够在下一次登录时免输入账号暗码。 |
记载用户偏好 | 在 Cookie 中存储用户的偏好设置,例如语言、主题、字体巨细等,以便用户下次拜访时康复相应的设置。 |
购物车 | 在 Cookie 中存储用户加入购物车的商品信息,以便用户能够在下次拜访时康复购物车状况。 |
个性化推荐 | 依据用户的前史阅读记载和偏好设置,在 Cookie 中存储相关数据,以便进行个性化推荐。 |
统计分析 | 在 Cookie 中存储用户行为数据,例如页面拜访次数、停留时刻等,以便进行统计分析和用户行为分析。 |
依据 JS 封装 Cookie 类
class MyCookie {
static set(name, value, options = {}) {
const { expires, path, domain, secure } = options;
document.cookie =
`${name}=${encodeURIComponent(value)}` +
(expires ? `; expires=${expires.toUTCString()}` : "") +
(path ? `; path=${path}` : "") +
(domain ? `; domain=${domain}` : "") +
(secure ? "; secure" : "");
}
static get(name) {
const cookieArr = document.cookie.split("; ");
for (let i = 0; i < cookieArr.length; i++) {
const [cookieName, cookieValue] = cookieArr[i].split("=");
if (cookieName === name) {
return decodeURIComponent(cookieValue);
}
}
return null;
}
static delete(name, options = {}) {
const { path, domain } = options;
document.cookie =
`${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC` +
(path ? `; path=${path}` : "") +
(domain ? `; domain=${domain}` : "");
}
}
// 测验用例示例
describe("Cookie", () => {
// 测验设置 Cookie
it("应该运用给定的称号、值和选项设置一个 Cookie", () => {
Cookie.set("test", "123", {
expires: new Date(Date.now() + 86400000),
path: "/",
domain: "example.com",
secure: true,
});
const cookie = document.cookie;
expect(cookie).toMatch("test=123");
expect(cookie).toMatch("expires");
expect(cookie).toMatch("path=/");
expect(cookie).toMatch("domain=example.com");
expect(cookie).toMatch("secure");
});
// 测验获取 Cookie
it("应该返回给定称号的 Cookie 的值", () => {
document.cookie = "test=123";
const value = Cookie.get("test");
expect(value).toBe("123");
});
// 测验删去 Cookie
it("应该删去具有给定称号和选项的 Cookie", () => {
Cookie.delete("test", {
path: "/",
domain: "example.com",
});
const cookie = document.cookie;
expect(cookie).not.toMatch("test=123");
});
});
Remix 中如何处理 Cookie
Remix 中对 Cookie 进行了封装, Remix 供给了 Cookie API
api 和特点
api 导入
import { isCookie, createCookie } from "@remix-run/node";
特点
const cookie = createCookie();
cookie.name; // 设置 Cookie 的名字
cookie.isSinged; // 是否运用了 secrets
cookie.expires; // 过期时刻
创立 createCookie
import { createCookie } from "@remix-run/node"; // or cloudflare/deno
export const userPrefs = createCookie("user-prefs", {
maxAge: 604_800, // one week
});
// 加密
const cookie = createCookie("user-prefs", {
secrets: ["s3cret1"],
});
userPrefs 具有: parse 解析/serialize 序列化
, 配合 Remix loader/action
来运用
import { userPrefs } from "~/cookies";
// loader/action
const cookieHeader = request.headers.get("Cookie");
const cookie = (await userPrefs.parse(cookieHeader)) || {};
// 序列化
redirect("/", {
headers: {
"Set-Cookie": await userPrefs.serialize(cookie),
})
判别是否 isCookie
import { isCookie } from "@remix-run/node";
const cookie = createCookie("user-prefs");
console.log(isCookie(cookie)); // true
Remix 官方运用示例
示例:gdpr-cookie-consent
- 设置 cookie
import { createCookie } from "@remix-run/node";
export const gdprConsent = createCookie("gdpr-consent", {
maxAge: 31536000, // One Year
});
- 处理 cookie
import type { ActionArgs } from "@remix-run/node";
import { json } from "@remix-run/node";
import { gdprConsent } from "~/cookies";
export const action = async ({ request }: ActionArgs) => {
const formData = await request.formData();
const cookieHeader = request.headers.get("Cookie");
const cookie = (await gdprConsent.parse(cookieHeader)) || {};
if (formData.get("accept-gdpr") === "true") {
cookie.gdprConsent = true;
}
return json(
{ success: true },
{
headers: {
"Set-Cookie": await gdprConsent.serialize(cookie),
},
}
);
};
假如只是运用 cookie 完成登录
长处:
- 不需求频频输入账号暗码,直接经过 cookie 传输
缺陷:
- 不安全,简单被篡改
- 假如多页面,需求频频读取 cookie 形成各种风险
依据 Cookie 的缺陷,这儿我们就需求引出 Session 绘画来弥补 Cookie 在登录等事务上的缺陷。
Session
Session 是一个在 Web 运用中跟踪用户会话状况的机制。当用户第一次拜访 Web 运用时,服务器会创立一个唯一的 Session ID,并将其存储在 Cookie 中返回给客户端。
Cookie-Session 作为一种 最简单
的鉴权办法, 广泛被运用。
Session 的主要效果
在服务器端存储用户的状况信息,这些信息能够是任何类型的数据,例如登录信息、购物车内容、用户配置等。
Session 的生命周期
阶段 | 描绘 |
---|---|
创立阶段 | 当用户第一次拜访网站时,服务器会创立一个唯一的 Session ID,并将该 ID 存储在 Cookie 中返回给客户端。 |
活动阶段 | 在用户会话期间,客户端的每个恳求都会带上 Cookie 中存储的 Session ID。服务器运用 Session ID 来获取对应的 Session 数据,以此来坚持用户状况和跟踪用户活动。 |
过期阶段 | 一般情况下,Session 有一个过期时刻,假如用户在一段时刻内没有活动,则服务器会删去该 Session 数据,以释放资源。 |
Session 的存储办法
Session 的存储办法 | 说明 |
---|---|
Cookie-based | 将 Session ID 存储在客户端阅读器的 Cookie 中,每次恳求时带着 Cookie 进行验证 |
Server-side | 将 Session ID 及其对应的数据存储在服务器端,客户端恳求时带着 Session ID 进行验证 |
Session 缺陷
- 有被绑架 Session ID 的可能,对 Session ID 的强壮性加强,也能够经过定期更换和有用的加密办法的等办法处理
- Session 与设备之间存在一对多,和多对一的联系,所以同享和同步的问题需求正确的处理。
Session 运用场景
Session 在 Web 运用中的运用 | 描绘 |
---|---|
用户认证和授权 | Session 能够存储用户登录状况和权限信息,完成用户认证和授权 |
购物车和在线付出 | Session 能够存储用户的购物车信息和付出状况,完成购物车和在线付出等功用 |
分布式运用的集群部署 | Session 需求完成同享和同步,以确保多个运用实例之间的数据一致性 |
Session 绑架和防范 | Session 可能被黑客进犯和绑架,需求采纳相应的安全措施 |
Session 同享和同步 | 分布式运用部署时,需求完成 Session 同享和同步,以确保多个运用实例之间的数据一致性 |
Session 数据加密和保护 | 为了提高数据的安全性,需求对 Session 数据进行加密和保护 |
Session 优化
Session 的优化和功用 | 描绘 |
---|---|
存储和读取优化 | 运用内存数据库如 Redis、Memcached 存储 Session 数据,以削减数据库的读写次数,并对 Session 数据进行序列化和反序列化 |
过期时刻和整理战略 | 依据事务需求和体系功用进行调整,例如依据用户活跃度、Session 数据量和服务器负载等进行设置 |
缓存和 Session 结合运用 | 运用分布式缓存如 Redis、Memcached 存储 Session 数据和缓存页面数据,以提高体系的呼应速度和并发拜访量 |
Remix 中 session
功用 | 办法名 | 描绘 |
---|---|---|
创立 session 目标 | createSession | 创立一个 session 目标 |
创立 session 存储库 | createSessionStorage | 能够方便地将 session 数据存储到外部数据库,而不是本机内存中 |
创立内存 session 存储库 | createMemorySessionStorage | 将所有的 session 数据保存在服务器内存中,速度较快但不行安全 |
创立依据文件的 session 存储库 | createFileSessionStorage | 能够将 session 数据保存到文件中,相对于内存存储愈加稳定和安全,但速度较慢 |
目前 Remix 也支撑了 Cloudflare Workder 和 Amazon Session 存储。
Remix 中 Session 规划与 Cookie 类似,运用办法也类似:
import { isSession, createSession } from "@remix-run/node";
// 界说 session 数据,创立 session 目标
const sessionData = { foo: "bar" };
const session = createSession(sessionData, "remix-session");
console.log(isSession(session));
session.has;
session.set;
session.flash; // `session.flash` 是一种在 Web 运用中完成音讯提示的机制。
session.get;
session.unset;
在 Loader 和 Action 中运用 Session
import { commitSession, getSession } from "../sessions";
export async function action({ params, request }: ActionArgs) {
// 从 getSession 和 Cookie 中获取 session
const session = await getSession(request.headers.get("Cookie"));
const deletedProject = await archiveProject(params.projectId);
// 设置首次读取时将取消设置的会话值
session.flash(
"globalMessage",
`Project ${deletedProject.name} successfully archived`
);
return redirect("/dashboard", {
headers: {
"Set-Cookie": await commitSession(session), // 提交 session
},
});
}
session 示例
- session-flash
- redis-upstash-session
小结
本文主要回忆了 cookie/session 的基础,然后运用了 Remix 中 cookie/session 的用法优缺陷,是运用 createCookie 函数创立 cookie, 以及特点和办法, 运用各种不的 session 创立办法并创立不同的 session 和其优缺陷以及 Remix 官方创立的示例。
微信查找并关注公踪号进二开物
,更多技能 JS/TS/CSS/Rust 文章…