Cookie 封装 - IE8下sessionStorage解决方案,chrome踩坑
前言须知(必知)
此次是为了实现项目中的tab打开效果,另外配有本地存储,刷新后打开的窗口还在,w3school、MDN上面查了下说IE8 是兼容sessionStorage,但是实际不然,下载了IETester之后,测试了下,IE8下直接为
undefined
, 故采用cookie 代替方案,代替session,最终目标兼容 IE8直到我做完我才发现,确实兼容,但是IE8 - IE10中是需要服务器或者localhost才能使用,也就是online 模式
但还是有在网上看到各种 难受的例子,做个前端不容易啊,一堆的坑等着你跳。
本文不是就一定推荐让你用
cookie
方案来代替sessionStorage
方案的,仅仅做一个参考,另外IE 还有自己存储解决方式UserDataStorage
cookies 带来的性能问题就是:作用域在指定的路径以及它的子路径都有效,并且会附加到请求中,这会发送很多不必要的数据。
本例使用环境为:
navigator.userAgent // 开发环境:谷歌78 Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36 // 测试环境 IE8 Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.2; WOW64; Trident/4.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729)
另外项目的tabs 打开关闭我还使用了:(可无视)
jquery-1.9.1 // 最终支持 IE8版本()
layui-v2.2.5 // 搭配layui 的基础模块 element 使用
本例是在chrome上开发完成后然后放到IETester 中去测试的,所以,接下来记录下遇到的坑
踩坑之路(新手必读)
1、cookie基础知识
cookie 的存储规则为:
字符串开头有可能有空格,可能没有(第一条就没有)
接着后面是 key= 的固定样式
字符串结束有可能有分号,可能没有(最后一条没有分号)
2、cookie扩展知识
cookie 的过期时间 关键词支持设置为 Expires 或者是 Max-age
注意 IE不支持 Max-Age 属性
cookie 的删除由浏览器自动处理,过期的cookie 将会删除
想删除一个 cookie 只需要把以前的时间赋值给对应的 Expires
过期时间不设置,默认为session ,关闭页面就没了
3、chrome开发中的坑
- chrome 会将设置的时间粗暴的转换成为晚八个小时的
GMT/UTC
时间
- 在
console
中 new 一个Date
查看注意 在设置cookie值与过期时间的时候 要用
;
隔开document.cookie = "age=21;" + "expires=" + new Date() + ";"
"age=21;expires=Fri Dec 13 2019 10:32:12 GMT+0800 (中国标准时间);"
- 而在使用cookie 存储后,谷歌浏览器会把时间弄成这样
T
,Z
代表ISODATE
2019-12-13T10:32:12.000Z //恭喜,喜提世界标准时间
- 然而我们国家是
GMT+0800
东八区,+得越大,越早看到太阳也就是说,我们设置的 cookie 要在八个小时后才会过期,才会被删除
- 在前端可认为GMT与UTC时间完全是一回事,都是指世界标准时间。
所以在这里应该存入我们国家的标准时间,可是chrome并不想这样
于是我们可以把时间 + 8小时存,或者干脆点,入乡随俗
"expires=" + new Date().toUTCString() + ";" //也可以 toGMTString
- chrome 使用
file
协议头打开文件时,不支持cookie
具体表现为:
A cookie associated with a cross-site resource at was set without the
SameSite
attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set withSameSite=None
andSecure
. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5088147346030592 and https://www.chromestatus.com/feature/5633521622188032.
翻译:
在处设置了与跨站点资源关联的cookie,但未设置SameSite属性,如果它们被设置了
SameSite=None
,并且它是Secure
,在未来的chrome版本中,我们只会将带有这些标识的 cookie 进行发送,您可以在Application > Storage > Cookies
下的开发人员工具中查看cookies
Chrome 51 开始,浏览器的 Cookie 新增加了一个
SameSite
属性,用来防止 CSRF 攻击和用户追踪。
CSRF
:(Cross-site request forgery) Cookie 往往用来存储用户的身份信息,恶意网站可以设法伪造带有正确 Cookie 的 HTTP 请求,这就是 CSRF 攻击。(跨站点请求伪造)SameSite 属性:
- Strict
- Lax
- None
详细:http://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html
这段话的意思也就是说,
Reject insecure SameSite=None cookies
我们拒绝不安全的 ,同站设置为无的cookies,并且没有携带
Secure
属性的cookies,输出的两个链接里面,可以点击进去看看。
解决方案:
chrome 浏览器不行,不代表其它浏览器不行([滑稽])
用online方式发布页面,在localhost 中打开,即可
CSDN大佬们给出的方案给chrome快捷方式添加 --enable-file-cookies启动参数
上代码
var cookieActive = {
setCookie:function (key,value,expir_sec) {
// 以多少秒为过期时间,模拟 后端的session默认单位
var d = new Date();
var millisec = d.getTime(); // 1970年1月1日0时0分0秒 到现在的时间(unix 时间戳)
d.setTime(millisec + expir_sec * 1000) // 化为毫秒
var expires = "Expires="+ d.toGMTString();
var cookie = key + "=" + encodeURIComponent(value); //解决存储中文的问题
if (typeof expir_sec === "number"){
cookie = cookie + ";" + expires
}
if (expir_sec === -1) //标识-1 为删除
{
cookie += "0;" + "expires=Thu,01-Jan-1970 00:00:01 GMT"
}
document.cookie = cookie;
},
getCookie:function (key) {
var reg = RegExp("(^| )"+key+"=([^;]*)(;|$)");//正则表达式了解下?
var cookie = document.cookie;
cookie = decodeURIComponent(cookie)
return (reg.exec(cookie) == null?null:reg.exec(cookie)[2])
},
delCookie:function (key,id) {
/*还好IE8支持 try catch*/
/*
* 该函数删除的时候有几种情况:
* 1. 删除单个 key 中的值,key的值为 一个普通的值
* 2. 删除单个 key 中的值,key的值为 一个JSON 格式的值
*/
try{
var item = JSON.parse(this.getCookie(key))
}
catch (e) {
// 因为不是删除JSON 中的某一条数据,那肯定是执行删除整个 key,
// 不是JSON格式的情况下,直接删除
this.setCookie(key,"",-1)
return ;
}
if(id){ // 在第二个参数有值的时候,删除指定id项
for (var i = 0 ; i < item.length ; i++)
{
if (item[i].id === id) // 这个 .id 之后要进行修改,才能达到通用
{
item.splice(i,1)
break;
}
}
// 兼容处理 在删除JSON 后留下的 [],也将其删除
if (item.length == 0)
{
this.setCookie(key,"",-1)
return ;
}
this.setCookie(key,JSON.stringify(item)) //操作完毕 提交splice的修改
return ;
}
// 是json格式的条件下,且只有一条json(length == 1)
//
this.setCookie(key,"",-1)
},
delAllCookies:function () {
//此函数具有一定的危险性,
var keys = document.cookie.match(/[^ =;]+(?=\=)/g);
if (keys){
for (var i = 0; i < keys.length; i++) {
this.setCookie(keys[i],"",-1)
}
}
}
}