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)的身份驗證。