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 的 protocol、port (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不香吗

你可能感兴趣的:(4种前端本地存储方法 在浏览器中持久化保存数据)