Cookie、localStorage、sessionStorage都是存储在浏览器端会话数据,接下来分别详细介绍三种机制。
一、cookie
1、什么是cookie
cookie 是存储于访问者的计算机中的变量。每当同一台计算机通过浏览器请求某个页面时,就会发送这个 cookie。cookie的作用是保存客户端上用户的信息包括登陆信息、偏好设置或者其他数据。在我一篇HTTP协议的文章中提到过Cookie,由于HTTP协议是一种无状态协议,每一次请求之间没有都是独立的,那么要保存用户的会话信息的话,就要在每一次HTTP请求过程中附带上Cookie发送给服务器。下面是我用fiddler获取www.qq.com的请求数据:
GET http://www.qq.com/ HTTP/1.1
Host: www.qq.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:51.0) Gecko/20100101 Firefox/51.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://e.firefoxchina.cn/?cachebust=20160321
Cookie:pt2gguin=o1137567854;ptcz=7d097f461558c3395939a07e244fef634e4f53ff88165b697835e925ffbf6df8; tvfe_boss_uuid=144c3d24ad91e75b; pgv_pvid=1738290900; o_cookie=1137567854; pgv_pvi=6978680832; RK=t12WR4aufe; ts_refer=e.firefoxchina.cn/; ts_uid=1209845192; pac_uid=1_1137567854
Connection: keep-alive
Upgrade-Insecure-Requests: 1
2、cookie的构成
名称:唯一确定一个cookie的名称。而且不区分大小写;经过URL编码。
值:存储在cookie的字符串。经过URL编码。如上面的ptcz=7d097f461558c3395939a07e244fef634e4f53ff88165b697835e925ffbf6df8;
域名:说明cookie在哪个域名下有效
路径:指定域中哪个路径对服务器发送cookie。比如指定http://www.qq.com/s/,下才能访问cookie,那么就不会向http://www.qq.com/发送cookie。
失效时间:指定cookie失效的日期。接受的是GMT格式的时间,可以用toGMTSting函数将其他时间格式转换为GMT格式的时间。如果设置了一个以前的时间。那么这个cookie立刻消失。
安全标志:直接指定为secure.表示只有在SSL连接时候才发送给服务器。也就是在HTTPS协议的时候才会发送cookie到服务器上。来看一条完整的cookie
Set-Cookie: IPLOC=CN4403; expires=Tue, 13-Mar-18 07:54:07 GMT; domain=.sogou.com; path=/
这是抓取百度的一条响应头信息里面的cookie。可以看到
名称: IPLOC,
值: CN4403。
失效时间为: 13-Mar-18 07:54:07 GMT。
域名为:.sogou.com
路径: 当前路径,也就是在整个域名下
安全标志: 没有
注意:
i:存储规则
一条cookie信息要遵循比较严格的模式,这是因为js下面所有的cookie值是保存在document.cookie下面的一个字符串里面。这样的话对于我们存取cookie值是非常不便的。为了能更好的存取cookie我们要有一种规定的格式。设置cookie的时候格式按照HTTP响应中set-cookie中顺序和格式。每一段信息都使用分号加上空格的方式分隔。等会再构造存取cookie时会详细讲解。
ii:哪些数据发送到服务器
只有名称和值会发送到服务器。其他属性只是服务器给浏览器的一个提示。
3、浏览器对cookie的限制
为了限制cookie不会被恶意用,以及不会占用太多磁盘空间,而且因为每一次请求的时候都要带上cookie,太多cookie会影响请求的性能。如此不同的浏览器会对cookie的数量和空间有响应的限制措施:
4、js中的cookie
js中cookie是一种不太友好的处理方式。它将所有的cookie存放在了docunment.cookie的字符串里面。比如:
name1=value1;name2=value2;name3=value3
而且js在设置一个cookie值得时候是这样的:
document.cookie="name=周运金";
这样并不会将之前的cookie值覆盖掉,这点需要理解。而且在设置cookie的时候只有名称和值是必须的。默认的过期时间实在你浏览器会话结束时间。上面提到过名称和值都必须经过URL编码,但是这里正好不需要进行URL编码(只有字母和数字[0-9a-zA-Z]、一些特殊符号”$-_.+!*’(),”[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL)
js采用encodeURComponent(string)函数进行编码。
比如设置一条cookie可以采用:
document.cookie=encodeURComponent("name")+"="+encodeURComponent("周运金")+"; domain=.yjblog.cn; path=/; expires="+(new Date("May 1,2017")).toGMTString();
5、JS中存取cookie的类
该类中封装了cookie的三种操作:读取、写入、删除;
var CookieUtil = {
// 设置cookie
set : function (name, value, expires, domain, path, secure) {
var cookieText = ""; //要设置的cookie字符串
cookieText += encodeURIComponent(name) + "=" + encodeURIComponent(value); //名称和值是必选参数,下面的可选
if (expires instanceof Date) { //检查时间是否标准格式
cookieText += "; expires=" + expires.toGMTString();
}
if (path) {
cookieText += "; path=" + path;
}
if (domain) {
cookieText += "; domain=" + domain;
}
if (secure) {
cookieText += "; secure";
}
document.cookie = cookieText;
},
// name=value; expires=expiration_time; path=domain_path; domain=domain_name; secure
// 获取cookie
get : function (name) {
var cookieName = encodeURIComponent(name) + "=",
cookieStart = document.cookie.indexOf(cookieName),
cookieValue = ""; //记得URL解码
if (cookieStart > -1) {
var cookieEnd = document.cookie.indexOf (";", cookieStart); //以;为标志,记得从cookieStart位置开始查找字符串
if (cookieEnd == -1) {//如果没有;说明到字符串尾部了
cookieEnd = document.cookie.length;
}
cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));//注意这里等号已经被跳过了,cookieStart + cookieName.length已经是从值得第一个字母开始了
}
return cookieValue;
},
// 删除cookie
unset : function (name, domain, path, secure) {
this.set(name, "", Date(0), domain, path, secure);
} //cookie的删除其实是将时间设置为过期
};
//设置cookie
CookieUtil.set("name","周运金");
CookieUtil.set("names","李佳家",new Date("May 1,2017"),"/s/",".yjblog.cn","secure");
//读取cookie
alert(CookieUtil.get("name"));
alert(CookieUtil.get("names"));
//删除cookie
CookieUtil.unset("name");
CookieUtil.unset("names");
//设置安全cookie
CookieUtil.set("names","李佳家",null,null,null,"secure");
//中间的参数用null填充,但是不能空缺
6、Cookie注意事项
i、存储太多cookie影响HTTP请求的性能
由于所有的cookie又会有浏览器作为请求头发送,所以cookie存储大量的诗句会影响到请求的性能,浪费带宽。cookie信息越多,请求的时间将越长,这是我们应该避免的。尽管浏览器对cookie做了限制,但是我们开发者应该在cookie少存储信息。(这就是需要Web Storage)
ii、安全性
由于HTTP采用的是明文模式,从我之前的关于通过xss攻击获取cookie
的文章可以看出,cookie的信息很容易被获取。所以对于一些敏感的数据比如用户账号密码、信用卡密码等都不要存放在cookie里面。
iii、数据丢失
当超过cookie限制的时候,有些浏览器如火狐会随机删除掉一些cookie以腾出空间给新的cookie,IE和Opera智能一点,会删除比较少用的cookie。
iiii、有些状态不可能保存在客户端
为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用。(这个就需要session来做了)
针对cookie大小限制以及数据量大会浪费带宽,HTML5标准出现了Web Storage克服cookie带来的限制。当数据被严格控制在客户端时,无需持续低将数据发回服务器。它的出现有两个主要的目的
1、提供一种在cookie之外存储会话数据的途径。
2、提供一种存储大量可以跨会话存在的数据机制。
主要有两种类型:sessionStorage、localStorage
二、sessionStorage与localStorage
1、什么是sessionStorage与localStorage?
从上一段中也可以大概猜出什么是sessionStorage/localStorage了。sessionStorage是类似于cookie可以将数据存储在浏览器端的一个对象。但是它不像cookie一样被发送到服务器,也因为这样sessionStorage有更大的容量,最大可以达到8M,适合存储比较大的数据。
2、sessionStorage的用法(包括localStorage的用法)
setItem存储value
用途:将value存储到key字段
用法:.setItem( key, value)
代码示例:
sessionStorage.setItem("name", "周运金");
localStorage.setItem("name", "李佳家");
getItem获取value
用途:获取指定key本地存储的值
用法:.getItem(key)
代码示例:
var value = sessionStorage.getItem("name");
var site = localStorage.getItem("name");
removeItem删除key
用途:删除指定key本地存储的值
用法:.removeItem(key)
代码示例:
sessionStorage.removeItem("name"); localStorage.removeItem("name");
clear清除所有的key/value
用途:清除所有的key/value
用法:.clear()
代码示例:
sessionStorage.clear();
localStorage.clear();
其他操作方法:点操作和[]
web Storage不但可以用自身的setItem,getItem等方便存取,也可以像普通对象一样用点(.)操作符,及[]的方式进行数据存储,像如下的代码:
var storage = window.localStorage;
storage.name= "周运金";
console.log(storage.name);
console.log(storage["name"]);
localStorage和sessionStorage的key和length属性实现遍历
sessionStorage和localStorage提供的key()和length可以方便的实现存储的数据遍历,例如下面的代码:
var storage = window.localStorage;
for (var i=0, len = storage.length; i < len; i++){
var key = storage.key(i); //先获取键名
var value = storage.getItem(key); //获取键值
console.log(key + "=" + value);
}
甚至还可以用for in遍历
for(var key in sessionStorage){
var value =sessionStorage.getItem(key);
alert(key+"="+value);
}
每次循环key会向指针一样指向sessionStorage的下一个键名。
3、storage事件
if(window.addEventListener){ window.addEventListener("storage",handle_storage,false);
}
else if(window.attachEvent){ window.attachEvent("onstorage",handle_storage);
}
function handle_storage(e){
if(!e){
e=window.event;
}
}
3、二者的区别
i、作用域
相同浏览器的不同页面间可以共享相同的 localStorage(页面属于相同域名和端口),但是sessionStorage只能在同源(相同域名相同端口)同窗口访问,但是当sessionStorage在同一窗口下转到同源页面还是可以访问的,因为这时候还是同源同窗口,不要单纯理解为两个不同的页面之间不能访问相同sessionStorage。比如你在A网页设置了一个sessionStorage的值,然后你同时在新的窗口下打开B网页,这时候你尝试在B网页得到A网页设置的sessionStorage是不可以的,但是当你在A网页跳转到B网页的时候,这时候你会发现B网页可以访问A网页中的sessionStorage。所以sessionStorage针对的是同源同窗口,不是同源同页面。
ii、生命周期
localStorage生命周期是永久,这意味着除非用户自己清除localStorage信息或者用户清除浏览器缓存,否则这些信息将永远存在。
sessionStorage生命周期为当前窗口或标签页,一旦窗口或标签页被永久关闭了,那么所有通过sessionStorage存储的数据也就被清空了。
总结:
cookie与sessionStorage、localStorage的区别
1、cookie可以在浏览器端与服务器端之间通信,是服务器端获取用户信息、保持一种持久客户端状态的关键。而sessionStorage、localStorage
虽然也可以保存会话数据,但是不能与服务器端进行信息交换。
2、cookie的容量比较小。而sessionStorage、localStorage有较大的容量
3、试用的浏览器范围不同。由于sessionStorage与localStorage是HTML5标准推出的,所以在IE7以及IE7以下的版本不适用。替代方案是采用IE的userData.(有兴趣可以了解一下)
最后:sessionStorage、localStorage的出现正好弥补了了cookie由于大小限制带来的问题,三者相辅相成为浏览器存储数据提供了更好的解决方案。