最近在调试程序的时候无意间看到 cookie 的过期时间是 session,这个 session 表示的是什么时候过期?牵扯出来另一个存储方案 sessionStorage 存储的数据又是什么时候过期呢?
在查找相关资料的时候总会看到会话结束的时候 cookie 会被清除,当然 sessionStorage 内的数据也会在会话结束的时候被清除。
问题又来了会话是什么?会话什么时候会结束?
暂时抛开这些问题,看看 sessionStorage 是怎么使用,和之前的持久化存储方案 cookie 有什么不同。
Storage
Storage 是 Web Storage API 的接口,localStorage 和 sessionStorage 都实现了这个接口,所以这两个对象都有这个接口定义的属性和方法。
-
:只读 存储的数据项数量
-
(n: number):返回存储的第 n 个键名
-
(key: string):返回 key 对应的值
-
(key: string, value: string):存储键和值,如果存在则更新
-
():清空存储的所有数据
Storage 和 cookies
cookie | localStorage | sessionStorage | |
---|---|---|---|
随 HTTP 发送 | 是 | 否 | 否 |
最大数据量 | 4K | 5M | 5M |
失效时机 | 自己定义 或 随着会话断开失效 | 不清除不失效 | 随着会话断开失效 |
跨域限制 | 是 | 是 | 是 |
下面是 MDN 对 sessionStorage 的描述:
sessionStorage 属性允许你访问一个,对应当前源的 session Storage 对象。它与 localStorage 相似,不同之处在于 localStorage 里面存储的数据没有过期时间设置,而存储在 sessionStorage 里面的数据在页面会话结束时会被清除。
页面会话在浏览器打开期间一直保持,并且重新加载或恢复页面仍会保持原来的页面会话。
在新标签或窗口打开一个页面时会复制*浏览会话的上下文作为新会话的上下文,这点和 session cookies 的运行方式不同。
打开多个相同的 URL 的 Tabs 页面,会创建各自的 sessionStorage。
关闭对应浏览器窗口(Window)/ tab,会清除对应的 sessionStorage。
上面的内容引用自MDN
对于以上的引用内容有如下问题:
什么是会话?
我理解会话是两个实体之间的交流,交流是一个过程,无论从时间还是从内容都会表现成一个过程,一段时间。例如:从输入账户密码进入系统到退出系统就是一次会话的完成。TCP 的三次握手也创建了一次会话,TCP 四次挥手关闭连接则关闭了会话。
重新加载或恢复页面,什么是恢复页面?
恢复页面就是浏览器窗口/tab 手动关闭或者意外关闭都是可以恢复的,恢复之后这个页面的会话也会随之恢复。前提是浏览器程序没有被退出,如果程序被退出了无论是手动退出还是意外退出 session storage 和 session cookies 都会被清除。
在新标签或窗口打开页面,是在哪里打开的新窗口或页面?复制*浏览会话,之后两个会话就没有联系了吗?
这里的打开新的标签/窗口指的是在当前页面触发的动作导致新窗口/tab 的打开。复制而来的会话(session storage)和之前的会话没有联系。
和 session cookies 的运作方式不同,session cookies 的运作方式是什么?
session cookies 的运作方式不是复制,不同窗口/tab 同一域操作的 cookies 是同一个。
加载别的页面是否算是会话结束?
不算会话结束,因为当前 tab 再次加载对应的 url 的时候还是可以访问到对应的 sessionStorage。
为了解答上面的问题,我的尝试如下:
-
在域 :80 下写入数据
('a', 1)
-
关闭当前 tab/窗口(保持浏览器程序没有退出)
-
历史记录 -> 最近关闭的 tab -> 刚才关闭的 tab
-
('a')
可以得到"1"
表明恢复的标签和之前的标签共享一个会话,因为它们是同一个标签
-
当前标签加载其它域名例如
-
在回来 :80 这时候可以通过
('a')
得到值"1"
表明同一个标签同一个域会共享会话
-
在当前页面通过链接
<a rel="opener" target='_blank' href=':80'>打开</a>
。(注意这里的ref属性,一定要加上,缺省则不会有效) -
在新开的 tab 下
('a')
可以得到得到值"1" -
在新开的 tab 下
('a', 2)
-
在原来的 tab 下
('a')
得到的还是 1
表明从当前域打开新的 tab/窗口会复制当前的会话作为新开页面的会话,因为是复制出来的,两个会话之间没有关联
-
关闭浏览器程序
-
再次打开浏览器,并且恢复 tab(不是新开 tab 打开同域页面)
-
('a')
得到的是 null 而不是"1"
表明关闭浏览器程序会结束会话
session cookies的失效
和 sessionStorage 的尝试一致,对于 cookie 的过期时间是 session 也做了如上尝试,得出的结论如下:
在浏览器关闭的情况下 session cookies 才会被清除,只是关闭相关 tab session cookies 还是存在,在此打开对应域的链接还是会看到相应cookies。
补充
- 对于
rel="noopener"
的a标签打开的链接不会复制opener
的sessionStorage,
参考Feature: Stop cloning sessionStorage for windows opened with noopener。 - 近期chrome浏览器修改了a标签
rel
属性缺省的默认值为noopener
,参考Feature: Anchor target=_blank implies rel=noopener by default。 - 关于a标签的
rel
属性可以参数考HTML attribute: rel
参考
MDN
MDN Storage
HTTP 会话原理解释与应用
sessionStorage 你可能会忽略的细节
实际中使用 Javascript 中 sessionStorage 的注意事项