文章目录
1.总述:
- WebApp 优异的性能表现,有一部分原因要归功于浏览器存储技术的提升。
- cookie存储数据的功能已经很难满足开发所需,逐渐被WebStorage、IndexedDB所取代
2.Cookie:
(1)来源:
-
HTTP是一种无状态的协议,客户端与服务器建立连接并传输数据后,连接就会关闭。再次交互数据需要建立新的连接,因此,服务器也无法知道用户上一次做了什么。
-
Cookie是用来绕开HTTP的无状态性的手段之一,服务器可以设置或读取Cookies中包含的信息,借此维护用户跟服务器会话中的状态。
-
比如在用户在购物网站上选择了一个商品后,服务器会发来一段cookie,里面保存了该商品的信息,然后在另一个页面选择了其他商品后,浏览器会把Cookie发送给服务器,服务器就知道他之前选购了什么。
(2)实现原理:
- 客户端请求服务器后,服务器会在响应头中通过set-cookie字段发送**包含登录凭据的
Cookie
**到客户端 - 浏览器在收到响应后会对该
Cookie
进行存储(内存或硬盘)。 - 用户再次发送请求时,会在请求头中通过cookie字段将该
Cookie
发送到服务器,然后服务器会对这个cookie进行用户身份,状态等验证。
生成cookie的两种方式:
-
服务器端在响应报文中添加set-cookie字段,通过ket-value的形式发送
//服务器端发送Cookie Set-Cookie: sid=121231 Set-Cookie: system:window_x64 //客户端发送Cookie Cookie: sid=121231; system=window_x64
-
在js中通过document.cookie来读写cookie
document.cookie="userName=hellol;domain=.baidu.com";
(3)Set-Cookie字段中可以设置的属性:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3qCNabwr-1601978817745)(C:\Users\刘小康\AppData\Roaming\Typora\typora-user-images\image-20201005160734368.png)]
-
有效期方面的属性:时间一到,浏览器会自动删除cookie文件
- Expires属性:用的是绝对时间点
- Max-Age属性:用的是相对时间,单位是秒,浏览器用收到报文的时间点再加上 Max-Age,就可以得到失效的绝对时间。
- 浏览器会优先采用 Max-Age 计算有效期。
-
作用域方面的属性:(为了安全,让浏览器仅发送cookie给特定的服务器和 URI,避免被其他网站盗用。)
-
domain属性:指定Cookie 所属的域名,指定只有该域名下的网站才可以访问该Cookie,例如要让Cookie在a.test.com下可以访问,但在b.test.com下不能访问,则可将domain设置成a.test.com。
-
path属性:指定Cookie 所属的路径。浏览器在发送 Cookie 前会从 URI 中提取出 host 和 path 部分,如果与cookie中的path不同,就不会在请求头里发送 Cookie。
-
-
安全性方面的属性:(为了不要让服务器以外的人看到)
-
HttpOnly属性:Cookie 只能通过HTTP 协议传输,禁止通过其他方式访问,例如会禁止通过js访问cookie,这样就减少了跨站脚本(XSS)攻击。
-
Secure属性:只能在协议为HTTPS的请求中携带cookie。
-
(4)Cookie如何防范跨站脚本(XSS)攻击:
跨站脚本功能是指攻击者在返回的HTML中嵌入javascript脚本,然后利用js盗取用户的cookie数据。
为了减轻这些攻击,需要在发送http请求时,在请求头中添加set-cookie字段的HttpOnly属性和Secure属性
跨站脚本(XSS)攻击的其他防范方法:对输入的url进行过滤,对输出的页面内容进行编码,阻止js脚本的执行。
跨站请求伪造(CSRF)是指攻击者欺骗用户点击链接,使其伪造了一个请求。可以通过添加token进行验证。
(5)存储类型:
Cookie
是由客户端保存的,按其存储位置可分为:内存式Cookie
和硬盘式Cookie
。
内存式Cookie
存储在内存中,浏览器关闭后就会消失,由于其存储时间较短,因此也被称为非持久Cookie或会话Cookie。
硬盘式Cookie
保存在硬盘中,其不会随浏览器的关闭而消失,除非手工清除或自动过期。由于硬盘式Cookie
存储时间是长期的,因此也被称为持久Cookie。
(6)应用场景:
- 一般都是用来维护用户的登录状态,即登录的时候选择记住密码,永久cookie就会被写在客户端电脑,下次登录时,自动将cookie信息附加发送给服务端。
- 购物车功能
- 记录用户的浏览记录,进行广告推荐
(7)缺陷:
-
Cookie 不够大,只能存储4KB的数据。
-
过多的Cookie会带来巨大的性能消耗,因为Cookie 是紧跟域名的。同一个域名下的所有请求,都会携带 Cookie。
- 对于静态文件的获取,不必在请求中加上cookie,可以将静态文件放在CDN上,这样请求的域名就与主站的域名分开了。
-
安全性问题,在http请求中cookie是通过明文传输的,使用https协议可以解决这个安全性问题。
HTML5中新增了本地存储的解决方案----Web Storage,它分成两类:sessionStorage和localStorage。
3.localStorage:
特点:
- 保存的数据长期存在
- 存储大小为5M左右
- 接口封装较好
使用方法:
//存数据
localStorage.setItem('name','liu')
//取数据
var name=localStorage.getItem('name')
应用场景:倾向于用来存储一些内容稳定的资源。比如图片内容丰富的电商网站会用它来存储 Base64 格式的图片字符串
4.sessionStorage:
特点:
- 会话级别的浏览器存储
- 存储大小也为5M左右
- 接口封装较好
使用方法:
//存数据
sessionStorage.setItem('name','liu')
//取数据
var name=sessionStorage.getItem('name')
应用场景:用来存储会话级别的信息,当前页面的浏览记录;
5.Cookie、localStorage、sessionStorage的区别:
- 共同点:都是保存在浏览器端,且都遵循同源策略。
- 不同点:生命周期,作用域,存储容量的不同
Cookie | localStorage | sessionStorage | |
---|---|---|---|
生命周期 | 在设置的失效时间到来之前一直有效。 | 持久化的本地存储,永久不会过期,只有手动删除 | 临时性的本地存储,会话级别的存储,当会话结束(页面被关闭)时,存储内容也随之被释放 |
作用域 | 只有指定的域名和路径可以访问 | 所有同源窗口可以共享 | 只存在于当前窗口 |
存储容量 | 4KB | 5M | 5M |
说到底,Web Storage 是对 Cookie 的拓展,它只能用于存储少量的简单数据。当遇到大规模的、结构复杂的数据时,Web Storage 也爱莫能助了。这时候我们就要清楚我们的终极大 boss——IndexedDB!
6.IndexedDB:
特点:
-
非关系型数据库,可以存储大量的结构化数据
-
拥有丰富的查询能力
-
支持事务回滚
-
支持存储二进制数据(ArrayBuffer对象和Blob对象)
三种会话跟踪技术:cookie,session,token
7.Cookie和Session的区别:
注意:Session指的是服务器端的缓存,而sessionStorage属于webStorage的一种,是浏览器端的缓存。
相同点:两者都是会话跟踪的技术,都是用来存储用户的信息
不同点:
- 存放位置不同:cookie存放于客户端,session存放于服务器端
- 安全性:cookie容易被窃取,不能存放敏感的信息,比如银行卡信息。考虑到安全性问题的话,应当使用session。
- 服务器性能:session会在一定时间内保存在服务器上。当访问增多时,会占用服务器的性能。考虑到减轻服务器性能方面,可以使用cookie。
- 存储对象:cookie存储的是字符串,session存储的是对象
- 作用域:服务器端的session是共享的,而cookie的作用域受到域名和路径的影响。
8.Cookie和Session的联合使用:
用户身份验证需要通过客户端的cookie和服务器端的session联合实现:
1、用户向服务器发送用户名和密码。
2、服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。
3、服务器向用户返回一个 session_id,写入用户的 Cookie。
4、用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。
5、服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。
9.Token与Session:
服务器端使用session进行登录认证的问题:
- 针对每一个用户都需要存储一个session,当越来越多的用户发请求时,内存的开销也会不断增加。
- 服务器集群需要同步所有的sesssion。
基于token的身份验证过程:
-
用户发送登录请求。
-
服务端返回一个签名的token 给客户端
-
客户端储存token,每次发送请求的时候都带上这个token
-
服务器端验证token并返回数据。
-
整个过程服务器端需要做的就是生成token,验证token,不需要再存储用户的身份信息。
token的优点:
- 安全性:由于token是经过签名认证的,所以可以防范CSRF(跨站请求伪造)
- 可扩展性:Token能够创建与其它程序共享权限的程序。
10.如何实现不同标签页之间的通信
考察的是数据存储的知识,数据存储有本地和服务器存储两种方式,这里前端我们只考虑本地存储
https://blog.csdn.net/qq_21729177/article/details/78028243
方法一:使用localStorage
原理:当同源页面的某个页面修改了localStorage
,其余的同源页面只要注册了storage事件,就会触发
//tab1 通过localStorage添加缓存
btn.onclick = function () {
window.localStorage.setItem("name", "liu");
};
//tab2 使用storae事件监听缓存增删改的动作
window.addEventListener("storage", function (event) {
//event.key中存储的是发生改变的cookie的键
//event.newValue存储的对应的值
if(event.key=="name"){
console.log(event.newValue)
}
alert("本地存储的数据有改变哦" + event.key + event.newValue);
});
方法二:通过postMessage实现跨域通信
应用场景:通过iframe有依赖关系的两个页面的通信
原理:通过window.postMessage发送消息,通过onMessage来监听消息
tab1: 引入iframe的页面
<body>
<input type="text" id="input" />
<button onclick="sendMessage()">点击向iframe发送数据</button><br />
<iframe
src="http://127.0.0.1:5500/3.test2.html"
frameborder="0"
allow=""
id="iframe"
></iframe>
</body>
<script>
function sendMessage() {
// 1.获取iframe窗口的引用
// 方法一:直接获取iframe的contentWindow属性
// contentWindow 属性返回当前HTMLIFrameElement的Window对象. 你可以使用这个Window 对象去访问这个iframe的文档和它内部的DOM
// var win = iframe.contentWindow;
// 方法二:通过window.frames获取
// 返回的是frame对象的集合,一个类数组对象,列出了当前窗口的所有直接子窗口
var win = frames[0];
// 2.向指定的窗口发送数据
//otherWindow.postMessage(message, targetOrigin);
//2.1 otherwindow表示指定的窗口,可以有三种情况:
//可以是iframe的contentWindow属性
//也可以是window.open返回的窗口对象
//还可以是window.frames中的子窗口
//2.2 第一个参数message表示要发送的消息
//2.3 第二个参数表示目标窗口的地址。注意:如果是/,则表示只发送消息给同源的页面;如果是*就表示将数据发送给全部页面。
win.postMessage(input.value, "http://127.0.0.1:5500");
}
</script>
tab2: iframe原页面
<body>
<div
id="iframe"
style="width: 500px; height: 500px; background-color: skyblue"
>
这是内嵌的iframe
</div>
</body>
<script>
// 监听通过postMessage向自己发来的数据
window.addEventListener("message", function (e) {
console.log(e);
// e.target表示发送方的原地址
// e.data表示发送过来的数据
// e.source表示对发送消息的窗口对象(即window对象)的引用,可以利用继续使用这个属性向原地址返回数据
// e.source.postMessage()
iframe.innerHTML = e.data;
});
</script>