设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 创业者 手机 数据
当前位置: 首页 > 站长学院 > MySql教程 > 正文

如何使用localstorage代替cookie实现跨域共享数据问题

发布时间:2020-05-12 02:22 所属栏目:115 来源:站长网
导读:副标题#e# 因为网站系统的日益庞大,不同域名业务,甚至不同合作方网站的cookie可能或多或少需要进行共享使用,遇到这个情况的时候,大家一般想到的是使用登录中心分发cookie状态再进行同步进行解决,成本较高而且实施起来比较复杂和麻烦。 因为cookie在跨

 

因为网站系统的日益庞大,不同域名业务,甚至不同合作方网站的cookie可能或多或少需要进行共享使用,遇到这个情况的时候,大家一般想到的是使用登录中心分发cookie状态再进行同步进行解决,成本较高而且实施起来比较复杂和麻烦。

因为cookie在跨域的情况下,浏览器根本不允许互相访问的限制,为了突破这个限制,所以有了以下这个实现方案,使用postmessage和localstorage进行数据跨域共享。

原理比较简单,但是遇到的坑也不少,这里梳理一下,做个备份。

二,API设计

背景中说过我们使用localstorage来代替cookie,本身localstorage和cookie就有一些使用上的区别,比如localstorage的容量更大,但是不存在过期时间,虽然容量大,但在不同的浏览器上也都有空间上限,操作不好很容易崩溃,还有就是postmessage虽然支持跨域,安全问题和api的异步化也给使用带来了一些麻烦,我们如何把这个模块设计的更易用呢?

先看下我设计的API:

import { crosData } from 'base-tools-crossDomainData'; var store = new crosData({ iframeUrl:"somefile.html", //共享iframe地址,iframe有特殊要求,详见模板文件 expire:'d,h,s' //单位天,小时,秒 默认过期时间,也可以种的时候覆盖 }); store.set('key','val',{ expire:'d,h,s' //option 可带过期时间,覆盖expire }).then((data)=>{ //异步方法,如果种失败,会进入catch事件 //data {val:'val',key:'key',domain:'domain'}; }).catch((err)=>{ console.log(err); }); store.get('key',{ domain:'(.*).sina.cn' //可以指定域名,也可以使用(.*)来匹配正则字符串,返回的val信息会带着domain信息,不填写则返回本域的 }).then((vals)=>{ console.log(val) //异步获取存储数据,可能多个,是个数组 [{},{}] }).catch((err)=>{ }); store.clear('key').then().catch(); //只清楚当前域下的key,不允许清除其他域下的key,只能读

一个模块上手快不快主要看api,所以对于一个数据共享模块,我认为支持set,get,clear这3个方法就ok了,因为postmessage本身是个一来一回的异步的行为,包装成promise的肯定更为合适和易用。因为localstorage不支持过期时间,所以需要一个全局的过期时间配置,当然也可以在set的时候进行单独配置,而get的时候我们可以指定获取某个域下的数据或者多个域下的数据,因为key名可能重复,但是域只有一个。这里就牵扯到了数据的管理,后边单独来说,最后clear和set的api只能种本域的数据,不可以操作其他域下的数据,get被允许。

下面我们看一下,client端的设置和API:

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>crosData</title> </head> <body> <script> window.CROS = { domain:/(.*).sina.cn/, //或者你允许的域名,支持正则和*通配符 lz:false //是否开启lz压缩val字符 }; </script> <script src=http://www.jb51.net/html5/"http:/cdn/sdk.js"></script> </body> </html>

你可以灵活在任何一个域下的一个html文档中,引入client的js sdk,然后通过全局属性的方式配置一个你允许被种到这个文档所在域下的domain白名单,支持正则,然后lz是是否启动lz-string压缩,至于什么是lz压缩后边我再介绍。

到这里,一个比较通用的API设计就完成了,下面我们看一下实现原理和具体的一些问题。

三,实现原理

说起来好想蛮简单的,但是写起来其实并不是,我们首先需要知道postMessage怎么用,这个属于很常见的一个API了,他有一个要点这里告诉大家,就是postMessage只能在iframe中或者使用window.open这种开启新页面的方式进行互相通讯,当然这里我们首先就要创建一个隐藏的iframe,进行跨域。

 

懒得拿工具画图了,因为流程比较清晰,这里拿文字复述一下整个通讯流程,首先父页面创建一个隐藏的iframe,然后当执行set,get,clear等command的时候,通过postMessage来进行消息广播,子页面接收到消息后,解析命令,数据和回调id(postMessage无法传递函数和引用,兼容问题导致,最好只传string类型,所以还需要对data做stringify)。然后当子页面处理完localstorage的操作后,再通过postMessage把对应的cbid和data返回给父页面,父页面监听message事件,处理结果。

四,编码

嗯,所以说没几行,我们下面开始进行编码了:

首先介绍一下我们用到的第三方包都有什么,为什么要用:

1,url-parse 对url进行parse解析,主要用他里面的origin属性,因为postMessage本身对origin就有严格的验证,我们要支持白名单和域名管理也需要。

2,ms 对时间简写做毫秒转换的工具库。

3, lz-string 对字符串做压缩用的工具包,这里给大家科普一下LZ压缩算法,首先了解LZ需要先了解RLZ,Run Length Encoding ,是一个针对无损压缩的非常简单的算法。它用重复字节和重复的次数来简单描述来代替重复的字节。LZ 压缩算法的背后是使用 RLE 算法用先前出现的相同字节序列的引用来替代。简单的讲, LZ 算法被认为是字符串匹配的算法。例如:在一段文本中某字符串经常出现,并且可以通过前面文本中出现的字符串指针来表示。

lz-string本身有优势就是可以大大的减小你的储存量,本身5MB的localstorage如果用来支持多域名的数据保存,很快就会被压缩用完,但是lz-string本身比较慢,消耗比较大,大家平时在工作中如果对传输数据量有大小要求的话可以尝试使用这个压缩算法来优化字符串长度,默认是不开启的。

4,store2 本身localstorage的api比较简陋,为了减少代码逻辑复杂度,这里选了一个比较流行的localstorage的实现库来进行store的操作。

说完了第三方包我们下面看一下父页面的js怎么来写:

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读