HTTP Cookie(也叫 Web Cookie 或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。是WEB项目开发需要涉及的内容。

Cookie操作

如果应用程序是完全客户端 SPA(单页应用程序),可能不需要 cookie,使用 localStorage 可以解决问题。如果是使用 Next.js 或者 Node.js 提供服务器接口需要身份验证 Token 的可以考虑使用 cookie

通常认为 cookie 是复数形式,但事实是它们存储在单个字符串值中,必须对其进行解析才能将它们分解为单独的键/值对

console.log(document.cookie); // _gcl_au=1.1.1660316496.1636468606; _ga=GA1.2.221099298.1636468607; _gid=GA1.2.1474751041.1636468607;

可以通过 ; 拆分字符串来将它们分开,然后映射每个值并使用 = 将其拆分为 ,最终将得到相应的键/值对。下面是一个完整的方法集:

const useCookie = (options = { days: 30, path: "/" }) => {
    const { days: expiresDays, path: cookiePath } = options;

    const set = (name, value) => {
        const exp = new Date();
        exp.setTime(exp.getTime() + expiresDays * 24 * 60 * 60 * 1000);
        const strExpires = exp.toGMTString();
        const cookieValue = escape(value);
        document.cookie = `${name}=${cookieValue};expires=${strExpires};path=${cookiePath}`;
    };
    const get = (name) => {
        let arr;
        const reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
        if ((arr = document.cookie.match(reg))) {
            return unescape(arr[2]);
        } else {
            return null;
        }
    };
    // 删除cookie
    const remove = (name) => {
        document.cookie = name + "=;expires=" + new Date(0).toGMTString();
    };
    // 清除所有 cookie
    const clear = () =>
        document.cookie
            .split(";")
            .forEach(
                (cookie) =>
                    (document.cookie = cookie
                        .replace(/^ +/, "")
                        .replace(
                            /=.*/,
                            `=;expires=${new Date().toUTCString()};path=${cookiePath}}`
                        ))
            );
    /**
     * 获取所有的 cookie
     * @returns
     */
    const all = () =>
        document.cookie
            .split(";")
            .map((item) => item.split("="))
            .reduce(
                (acc, [k, v]) => (acc[k.trim().replace('"', "")] = v) && acc,
                {}
            );
    return {
        set,
        get,
        clear,
        remove,
        all,
    };
};
const cookieHelper = useCookie();
cookieHelper.set("name", "DevPoint");
cookieHelper.set("city", "Shenzhen");
console.log(cookieHelper.get("name")); // DevPoint
console.log(cookieHelper.all()); // { name: "DevPoint", city: "Shenzhen" }
cookieHelper.remove("name");
console.log(cookieHelper.all()); // { city: "Shenzhen" }

出于安全考虑,某些 cookie 可能被标记为 仅 HTTP ,这意味着此类 cookie 不能从客户端的 JavaScript 代码中获取到。

Cookie 安全主要涉及以下两个方面:

防止窃取

攻击者可以通过窃取用户的 Cookie 来实现会话劫持等攻击,因此在设置 Cookie 时应当注意以下安全问题:

  • 在服务器端设置 HttpOnly 属性,防止脚本获取 Cookie。
  • 使用 secure 属性,只允许在 HTTPS 连接中传输 Cookie。
  • 设置 SameSite 属性,防止跨站请求伪造攻击(CSRF)。

防止篡改
攻击者还可以通过修改 Cookie 的值来实现攻击,因此在使用 Cookie 时应当注意以下安全问题:

  • 在服务器端对 Cookie 的值进行加密和签名,防止篡改。
  • 对于关键操作,应当在服务端进行校验,避免因为 Cookie 被篡改而造成安全漏洞。

综上所述,Cookie 安全需要从多个方面进行考虑和防护。

应用开发一般都少不了身份验证,而身份验证机制的稳定性对所有应用程序都变得至关重要。具体选择何种方式进行身份验证可以根据项目及团队情况来衡量,在决定之前需要先理解WEB身份验证常见的两种方式:基于 Cookie 的身份验证和基于令牌(Token)的身份验证。