浏览器 - Cookie基础

Cookie 基础知识

概述

由于 HTTP 是无状态协议,在 localstorage 和 sessionStorage 出现之前 cookie 是存储状态的唯一方式,每一次 HTTP 的请求都会带上 cookie。

什么是 cookie?

cookie 是 document 对象上的一段由键值对构成的字符串,最大字节长度为 4KB,每个域至多20个 cookie,cookie 的格式如下:

<cookie-name>=<cookie-value>;<cookie-name>=<cookie-value>

cookie、localStorage 和 sessionStorage 有什么区别?

容量不同:cookie 最多可储存 4KB 的内容,storage 可以储存 5至10MB 的内容;

有效期不同:cookie 在过期时间之前一直有效,localStorage 除非主动删除否则一直有效,sessionStorage 在当前页面关闭前有效;

构成

属性 说明
domain
指定哪些域名可以访问该 cookie,默认为 origin(当前域名),不包含子域名,如果手动设置 domain 为 .google.com,则包含其子域名(大多数浏览器域名前不加点号也包含其子域名)
path 指定同源域名下的哪些路径可以访问该 cookie,当设置 path 为 /goods时,/goods/goods/apple都可访问 cookie
samesite samesite 用于限制跨站读取 cookie,防止CSRF攻击,他有三个值:none、strict、lax
none:同站和跨站都会发送 cookie
strict:只在同站时会发送 cookie
lax:默认值,处于同站时会发送,某些条件下跨站也会发送 cookie(点击页面 a 标签跳转、js 进行页面跳转/新开页、Get请求提交表单)
secure 是否只在 https 协议下传输,值为 true | false
httponly 是否只允许通过 http 传输,不允许 js 获取到 cookie
expires cookie 过期时间,他的值是 UTC 时间,可以通过Date.prototype.toUTCString()方法将 Date 对象转换成 UTC 字符串
max-age 从此刻开始 cookie 存活的秒数,max-age 的优先级高于 expires。
如果响应头的 set-Cookie 字段没有指定 expires 和 max-age,那么返回的 cookie 只会在本次对话存在,关闭页面后 cookie 将会消失

服务端

服务器可以设置响应头的 Set-Cookie 字段,浏览器接受到服务器的响应后会自动设置 cookie。

举个例子:

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;

JS

这里整理了一个用于修改 cookie 的类:

class Cookix {
  // 判断查找项是否存在
  static has(name: string) {
    return new RegExp(`(^| )${name}=([^;]*)`).test(document.cookie) && Cookix.get(name) !== "";
  }

  // 获取查找项的值
  static get(name: string) {
    const _match = document.cookie.match(new RegExp(`(^| )${name}=([^;]*)`));
    if (!_match) return null;
    return _match[2];
  }

  // 新增/替换新的cookie
  static set(
    name: string,
    options: {
      value: string;
      domain?: string;
      path?: string;
      maxAge?: number;
      expires?: string;
      samesite?: string;
      secure?: boolean;
    }
  ) {
    const defaultOptions = {
      domain: "",
      path: "/",
      maxAge: "",
      expires: "",
      samesite: "lax",
    };

    const optionsClone: { [key: string]: string | number | boolean } = { ...defaultOptions, ...options };
    const optionArray = Object.keys(optionsClone);

    let optionStr = optionArray
      .filter((item) => item !== "value" && optionsClone[item] !== "")
      .map((key: string) => `${key}=${optionsClone[key]}`)
      .join(";");
    optionStr += optionsClone.secure ? ";secure;" : ";";

    document.cookie = `${name}=${options.value};${optionStr}`;
  }

  // 删除指定cookie
  static remove(name: string, options?: { domain?: string; path?: string }) {
    const defaultOptions = {
      domain: "",
      path: "/",
      value: "",
      expires: "Thu, 01 Jan 1970 00:00:00 UTC",
    };
    const _options = { ...defaultOptions, ...options };
    Cookix.set(name, _options);
  }
}

export default Cookix;
作者

BiteByte

发布于

2021-04-17

更新于

2024-01-11

许可协议