Web前端入门第 81 问:JavaScript cookie 的读写操作

前端的 cookie 读写在 2020 年之前一直不存在一个官方的接口,每次需要使用 cookie 的时候,要么是引入三方插件,要么就需要自己封装一个公用的组件或函数。

npm 的 cookie 插件周下载量 6 千万左右,可以想象一下此功能在前端的应用场景有多么广泛~~

cookie 插件: https://www.npmjs.com/package/cookie

cookie 一般多用于存储标识符,比如用户身份标识(登录状态),个性化设置的一些标识(语言设置,主题设置等等),用户行为跟踪标识(跟踪用户点击行为等)。

以前还有很多的广告商用于跟踪用户行为,现在由于浏览器的安全机制越来越严格,广告商基本不再使用 cookie 跟踪用户信息,转而使用浏览器的指纹特征来做跟踪记录。浏览器指纹可参考文章:浏览器 15 个常见指纹特征,使用插件 FingerprintJS 生成浏览器指纹

由于 cookie 存储在用户浏览器,极易被嵌入的三方代码获取,用于 XSS 攻击,CSRF 跨站请求伪造等等。

所以在使用 cookie 存储关键信息时候,需要注意配置 cookie 的安全属性,比如:过期时间(expires)、安全(secure)、sameSite等。

name:记录 cookie 名称的字符串。
value:记录 cookie 值。
domain:表示 cookie 的所属域,跨域不能访问。
expires:表示 cookie 的过期时间,使用 unix 时间戳,不设置默认是会话结束,即浏览器关闭就失效。
path:记录 cookie 路径的字符串,设置了路径之后,跨路径无法访问。默认为 /。
partitioned:cookie是否分区,实验性质。
sameSite:设置跨站点请求中是否发送cookie。
secure:设置后表示只能通过 HTTPS 协议访问。


以下属性仅支持后端设置,前端无法处理。
httpOnly:设置后客户端脚本(即浏览器端)无法访问 cookie。

最原始的 cookie 存储方法只能使用 document.cookie 属性,读写操作都只能通过它~~

例如一个完整的设置 cookie 的代码:

/* by 01022.hk - online tools website : 01022.hk/zh/formatruby.html */
document.cookie = `name=${encodeURIComponent('前端路引')};expires=${new Date(2026, 0, 1).toGMTString()};path=/;Secure;SameSite=Lax`;

注意:写入 cookie 的属性值不能存在换行,换行无效,代码也不会报错,比如:

/* by 01022.hk - online tools website : 01022.hk/zh/formatruby.html */
// 由于有换行符存在以下代码浏览器不报错,也不会写入cookie
document.cookie = `
  name=${encodeURIComponent('前端路引')};
  expires=${new Date(2026, 0, 1).toGMTString()};
  path=/;
  domain=localhost;
  Secure;
  SameSite=Lax
`;

取值:

const name = document.cookie.split(';').find(item => item.trim().startsWith('name=')).split('=')[1]
console.log(decodeURIComponent(name))

这种读写方法始终不太方便,然后可以稍稍的封装一下:

/**
 * 获取或者设置cookie
 * @param name {String} cookie名
 * @param value {String} cookie值,如果传递该参数,则直接取值
 * @param days {Number} 设置cookie有效天数
 * @return 如果取值,则返回值,没值则返回null
 */
function cookie (name, value, days) {
  if (value !== undefined) {
    if (days === undefined || days === null || days === '') {
      document.cookie = name + '=' + encodeURIComponent(value) + '; path=/;';
      return;
    }
    days = isNaN(days) ? 0 : days;
    var exp = new Date();
    exp.setTime(exp.getTime() + days * 24 * 60 * 60 * 1000);
    document.cookie = name + '=' + encodeURIComponent(value) + '; path=/;expires=' + exp.toGMTString();
  } else {
    var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)');
    var arr = document.cookie.match(reg);
    if (arr) {
      return decodeURIComponent(arr[2]);
    } else {
      return null;
    }
  }
}

以上代码只是一个基础的封装使用,可以基于此扩展一下其他配置项!!也可以直接下载 npm 开源的 cookie/js-cookie 插件。

CookieStore

document.cookie 操作 cookie 需要对字符串进行处理,如果存在多个 cookie 的情况下,处理起来就更麻烦,所以在 2020 年 JS 标准就新增了 CookieStore 接口,用于管理 cookie。此接口大大的简化了 cookie 的读写操作,用起来也更加方便。

CookieStore 只能在 https 或者 localhost 下使用,所以不再支持 Secure 配置,默认就是在 https 中传输。

CookieStore 对象就四个方法,都返回 Promise 对象:

// 删除
cookieStore.delete() // 返回 Promise
// 获取
cookieStore.get() // 返回 Promise
// 获取全部
cookieStore.getAll() // 返回 Promise
// 写入
cookieStore.set() // 返回 Promise

// 支持change事件用于监听 Cookie 变化
cookieStore.addEventListener("change", (event) => { })
cookieStore.onchange = (event) => { }

使用示例:

(async () => {
  cookieStore.addEventListener("change", (event) => {
    console.log(event.changed);
  })
  cookieStore.onchange = (event) => {
    console.log(event.changed);
  }

  
  await cookieStore.set('name', '公众号')
  await cookieStore.get('name').then(value => {
    console.log(value)
  })
  await cookieStore.delete('name').then(() => {
    console.log('删除成功')
  })
  await cookieStore.set({
    name: 'name',
    value: '前端路引',
    expires: new Date(2026, 0, 1).getTime(), // Unix 时间戳(以毫秒为单位表示)
    path: '/',
    secure: true, // 不支持设置
    sameSite: 'lax'
  })
  await cookieStore.get({
    name: 'name',
    url: window.location.href
  }).then(value => {
    console.log(value)
  })
  await cookieStore.set('type', '公众号')
  await cookieStore.getAll().then(values => {
    console.log(values)
  })
})()

更多用法参考 MDN 文档:https://developer.mozilla.org/zh-CN/docs/Web/API/CookieStore

写在最后

cookieStore 可以大大简化前端读写 cookie 的复杂度,但由于其 API 引入时间较晚,基本都是在 2020 年之后的浏览器才开始支持,所以在使用时请注意浏览器兼容情况。

在使用 Cookie 保存敏感数据时,请务必注意数据安全,比如存储用户的身份令牌,如果身份令牌被三方代码获取,及其容易造成跨站请求伪造,导致用户信息泄露!!

 

文章首发于微信公众号【前端路引】,欢迎 微信扫一扫 查看更多文章。

本文来自博客园,作者:前端路引,转载请注明原文链接:https://www.cnblogs.com/linx/p/19000174

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值