4种前端本地存储方法 在浏览器中持久化保存数据

常见的4种前端存储数据的方式是cookie,LocalStorage,session sorage,IndexedDB

其中sessionStorage有时效性,仅在当前会话有效,当前会话结束后就会删除.

所以实质上,用于长期存储的方式只有3种,

下面放出他们进行对比的表格

其中indexDB相当于本地数据库,所以单独拿出来说

对比项目 cookie localstorage sessionStorage
数据存储时间 可设置失效时间 永久 仅当前会话
容量 <=4kb <=5mb <=5mb

其中三种方式都有原生api,其中cookie的原生api比较难用,cookie还有一个特点是会随着请求携带,并且可以被服务端随意修改

因此得出结论,一般网页应用用localstorage就行了,5mb存储一个应用的配置信息还是挺宽裕的.

另外会话中临时会使用的信息就用sessionStorage

cookie

cookie的主要属性表格

key value
Name cookie的名称
Value cookie的值,最大容量4Kb
Domain cookie存储的域名
Path cookie存储的路径
Size cookie的大小
Expires 过期时间,值可以是UTC格式,可以使用 Date.prototype.toUTCString() 进行转换
Max-Age 优先级高于Expires,设置cookie存活的秒数
HttpOnly 安全性,设置这个属性后,cookie就不会被js获取到,只有在发起请求时会带上
Secure 不需要设置,当协议是https时,自动开启,指定浏览器只有在加密协议 HTTPS 下才能发送cookie\
SameSite 跨站策略,设置为Lax,即仅允许同站或子站访问cookie;None:允许所有跨站cookie,设置为Lax会导致第三方cookie失效

cookie的原生api还是比较不人性化的,需要拼接字符串.所以一般我们会进行封装

下面是原生api的封装

设置cookie

/**
 * 设置cookie
 * @param {*} key 名称
 * @param {*} val 值
 * @param {*} time 失效时间
 */

export const setCookie = (key, val, expiresDays) => {

  var date = new Date();

  //将时间转换为cookie设置时间的格式

  date.setTime(date.getTime() + expiresDays * 24 * 3600 * 1000);

  document.cookie = key + "=" + val + ";expires=" + date.toDateString();
}

获取cookie

/**
 * 获取cookie
 * @param {*} key 名称
 */

export const getCookie = (key) => {

  var getCookie = document.cookie.replace(/[ ]/g, "");

  var arrCookie = getCookie.split(";")

  var tips;

  for (var i = 0; i < arrCookie.length; i++) {

    var arr = arrCookie[i].split("=");

    if (key == arr[0]) {

      tips = arr[1];

      break;

    }

  }

  return tips;

}

删除cookie

可以直接调用setCookie,把cookie的失效时间设置为-1即可

setCookie(key,'',-1)

利用第三方cookie追踪用户

cookie执行同源策略

同源的定义为:如果两个 URL 的 protocolport (en-US) (如果有指定的话)和 host 都相同的话,则这两个 URL 是同源

下表给出了与 URL http://store.company.com/dir/page.html 的源进行对比的示例:

URL 结果 原因
http://store.company.com/dir2/other.html 同源 只有路径不同
http://store.company.com/dir/inner/another.html 同源 只有路径不同
https://store.company.com/secure.html 失败 协议不同
http://store.company.com:81/dir/etc.html 失败 端口不同 ( http:// 默认端口是80)
http://news.company.com/dir/other.html 失败 主机不同

所以说如果在当前网站上你是无法设置和获取不同原的cookie的.

但是我们利用下面两个特性可以实现第三方cookie,追踪用户.

  • 服务端可以设置cookie
  • cookie会随着请求携带

举例一个利用第三方cookie的广告

假设a网站引入了一个c的广告组件,这个组件请求另一个网站c的服务端来设置cookie,这时你的浏览器上就有c的cookie了

这时你再访问同样引入c的广告组件的b网站,此时你浏览器上已经有访问a时c的cookie,因此能识别出你是同一个用户,从而给你显示一样的广告.

cookie 防止XSS攻击

如果我们的网站没有对用户输入进行过滤,就有可能造成xss攻击.

攻击者可以通过调用document.cookie获取后把我们的cookie发送给攻击者.

但是如果我们设置了HttpOnly属性后,document.cookie就获取不到cookie了,提高了安全性

cookie会被利用于CSRF攻击

跨站请求伪造利用了cookie会被请求自动携带的特性.

比如你的电脑中有银行的cookie,你在打开银行的页面的同时,打开了一个钓鱼网站,这个网站包含对银行发起请求的图片标签,直接把你的一大笔钱转走了...因为浏览器在请求银行的时候会自动把cookie带上,这样银行的服务器就会以为是已经登录的用户的请求.

一般为了防止csrf,会增加其他的安全验证token.

或者直接不使用cookie,而使用localStorage,loacalStorage也会被xss利用,所以要注意对用户输入进行过滤.

localStorage和sessionStorage

这两个api都是随着html5加入的新api

这两者的主要区别是时效性不同,大小都为5mb

两者的api也是一样的

主要是以key value形式的字符串存储

缺点

localStorage的缺点是,只能存入字符串,无法直接存储对象,所以我们每次存入和取出都要重新json处理一下...

而JSON.stringify()我们知道,它对undefined funtion等一些类型无法正常处理,并且不能转换循环引用的对象,因此使用时需要注意.

存储storage

/**
 * 存储Storage
 */
export const setStore = (params = {}) => {
  let {
    name,//名称
    content,//内容
    type,//类型
  } = params;
  let obj = {
    dataType: typeof (content),
    content: content,
    type: type,
    datetime: new Date().getTime()
  }
  if (type) window.sessionStorage.setItem(name, JSON.stringify(obj));
  else window.localStorage.setItem(name, JSON.stringify(obj));
}

获取storage

/**
 * 判断是否为空
 */
function validatenull (val) {
  if (typeof val === 'boolean') {
    return false
  }
  if (typeof val === 'number') {
    return false
  }
  if (val instanceof Array) {
    if (val.length == 0) return true
  } else if (val instanceof Object) {
    if (JSON.stringify(val) === '{}') return true
  } else {
    if (val == 'null' || val == null || val == 'undefined' || val == undefined || val == '') return true
    return false
  }
  return false
}

/**
 * 获取Storage
 */
export const getStore = (params = {}) => {
  let {
    name,//名称
    debug//是否需要转换类型
  } = params;
  let obj = {},
    content;
  obj = window.sessionStorage.getItem(name);
  if (validatenull(obj)) obj = window.localStorage.getItem(name);
  if (validatenull(obj)) return;
  try {
    obj = JSON.parse(obj);
  } catch{
    return obj;
  }
  if (debug) {
    return obj;
  }
  if (obj.dataType == 'string') {
    content = obj.content;
  } else if (obj.dataType == 'number') {
    content = Number(obj.content);
  } else if (obj.dataType == 'boolean') {
    content = eval(obj.content);
  } else if (obj.dataType == 'object') {
    content = obj.content;
  }
  return content;
}

删除storage

/**
 * 删除localStorage
 */
export const removeStore = (params = {}) => {
  let {
    name,
    type
  } = params;
  if (type) {
    window.sessionStorage.removeItem(name);
  } else {
    window.localStorage.removeItem(name);
  }
}

获取storage

/**
 * 获取全部Storage
 */
export const getAllStore = (params = {}) => {
  let list = [];
  let {
    type
  } = params;
  if (type) {
    for (let i = 0; i <= window.sessionStorage.length; i++) {
      list.push({
        name: window.sessionStorage.key(i),
        content: getStore({
          name: window.sessionStorage.key(i),
          type: 'session'
        })
      })
    }
  } else {
    for (let i = 0; i <= window.localStorage.length; i++) {
      list.push({
        name: window.localStorage.key(i),
        content: getStore({
          name: window.localStorage.key(i),
        })
      })

    }
  }
  return list;
}

清空全部storage

/**
 * 清空全部Storage
 */
export const clearStore = (params = {}) => {
  let { type } = params;
  if (type) {
    window.sessionStorage.clear();
  } else {
    window.localStorage.clear()
  }
}

localStorage扩容

LOCALFORAGE是一个兼容性强的本地存储库,它的api类似于localStorage,

它对localStorage,webSQL,和indexedDB做了个平滑升级处理.

默认使用的是indexed和webSQL,在你的浏览器不支持这两个的时候才会降级使用localStorage

https://github.com/localForage/localForage

indexedDB

indexedDB是一个本地关系型数据库.和webStorage同期普及到浏览器的.

算是一个前端的终极本地数据存储方案

对比localStorage,有以下优势

  • 存储量理论没有上限(实际上各个浏览器还是会进行一定的限制的)
  • 支持异步操作,性能会更高.
  • 原生支持存储js对象
  • 是个数据库,功能强大

indexexDB最大的缺点是,api比较难用,功能繁琐.

一般我们用LOCALFORAGE(https://github.com/localForage/localForage)就行了,一定要用indexedDB的场合也比较少,如果这样通常不如做成客户端,我用sqlite不香吗

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容