数据缓存方案一:Cookie
很多Web项目会需求能够直接在客户端上存储用户信息能力的要求,无论是登录信息、偏好设定或其他数据,我们在开发Web应用的时候会找各种各样的方式将数据存储在客户端。
1. Cookie
Cookie
的标准要求服务器对任意http请求发送Set-Cookie HTTP
头作为响应的一部分,其中包括会话信息。
服务响应头如下:
http/1.1 200 OK
Content-type : text/html
Set-Cookie: name=value
Other-header:other-header-value
这个
http
设置以name
为名称、以value
为值的一个cookie
,名称和值在传送时必须是URL编码的。
浏览器会存储这样的会话信息,并在这之后,通过每个请求添加Cookie HTTP
头将信息发送回服务器
服务请求头如下:
GET /index.html HTTP/1.1
Set-Cookie: name=value
Other-header:other-header-value
传回服务器的额外信息可以用于唯一验证客户来自于发送的哪个请求。
cookie的限制
Cookie
性质上是绑定在特定的域名下的,到服务器返回的数据设定Cookie
后,再发送请求时,都会包含这个cookie。这个限制确保了存储在Cookie
中的信息只能让批准的接受者访问,而无法被其他域访问。- 单个域下
Cookie
的数量,和单个Cookie
的长度都是有限制的(根据浏览器的不同,限制各有差异)
,超过限制的数量后,再设置Cookie
,浏览器会清除以前设置的Cookie
。
cookie的构成
- 名称:一个唯一确定
Cookie
的名称。(注意名称是不区分大小写的,MYcookie和mycookie是同一个cookie
)- 值:储存在
Cookie
中的字符串。值必须被URL编码。- 域:
Cookie
对于哪个域是有效的。如果没有明确设置这个值,默认为设置Cookie
的域为指定域。- 路径:对于指定域中的哪个路径,应该向服务器发送cookie。
- 失效时间:指定
Cookie
何时被删除(何时停止向服务器发送cookie
)。默认情况下会话结束浏览器就会删除所有Cookie
,值是GMT格式的日期。- 安全标志:指定后,cookie只能在使用SSL链接的时候才发送到服务器。比如,cookie只能发送给“https:www.xxxx.com”,而“http:www.xxxx.com”的请求却不能发送cookie。
上面的每一段信息作为Set-Cookie
头的一部分,使用分号和空格分割,基本的构成如下:
HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value; expires=Fri, 26-Apr-2019 16:11:25 GMT; domain=.xxx.com;
Other-header: other-header-value
secure
标志是cookie
中唯一一个非名值对(key=value
)的部分,如下:
HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value; domain=.xxx.com; path=/; secure //secure
Other-header: other-header-value
secure
标志的存在,上面的cookie
只能在使用SSL链接的时候才发送到服务器。- 所有的名值对的参数会作为发送到服务器的
cookie
信息的一部分,而secure
标志不会。
2. JavaScript中的Cookie
读取
document.cookie
属性可以获取当前页面可用的所有cookie
的字符串,形式如下:
name1=value1;name2=value2;name3=value3;
document.cookie
获取到的字符串,需要用decodeURIComponent()
方法来解码。
设置
document.cookie
属性可以设置为一个行的cookie
字符串。
document.cookie = "name=value; expires=expiration_time; domain=domain_path;"
- 这些参数中,只有
cookie
的名字和值是必须的。- 每次设置都是创建一个新的
cookie
,会被添加到现有的cookie
集合中。- 假如设置了重名的
cookie
,那么将会覆盖之前设置的。
不要忘了编码,encodeURIComponent()
document.cookie = encodeURIComponent("name")+" = "+encodeURIComponent("value")
3. Cookie的操作封装
我们可以根据Cookie
的 读取、写入和删除。来进行方法封装;
var cookieUtil = {
get: function (name) {
var cookieName = encodeURIComponent(name) + "=",
cookieStart = document.cookie.indexOf(cookieName),
cookieValue = null;
if (cookieStart > -1) {
var cookieEnd = document.cookie.indexOf(":", cookieStart);
if (cookieEnd == -1) {
cookieEnd = document.cookie.length;
}
cookieValue = decodeURIComponent(document.cookie.substring(cookieStart +
cookieName, cookieEnd))
}
return cookieValue;
},
set: function (name, value, expires, path, domain, secure) {
var 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;
},
unset: function(name, path, domain, secure){
this.set(name, "",new Date(0), path, domain, secure)
}
}
//设置Cookie,路径、域、失效日期
var dd = new Date();
var expires = new Date(dd.setDate(dd.getDate() + 1));//获取1天后的日期
CookieUtil.set('name', 'Nicholas', '/books/projs/', 'www.xxx.com', expires)
//删除设置的Cookie
CookieUtil.unset('name')
//设置安全的cookie
CookieUtil.set('name', 'Nicholas', '/books/projs/', 'www.xxx.com', expires, true)
在DOM中并没有直接删除
cookie
的方法,所以需要使用相同的路径、域和安全标志再次设置cookie
,并且设置它的过期时间为过去的时间。这样就可以将失效的cookie
替换现在需删除的cookie
了。
4. 子cookie了解一下
子cookie
是为了绕开浏览器的单域名下的cookie
数限制,也就是使用子cookie
值来存储对个名称值对,使cookie
更加结构化。如下:
name=name1=value1&name2=value2&name3=value3&name4=value4&name5=value5
5. 子Cookie的操作封装(简单说一下获取指定name)
var subCookieUtil = {
get(name,subName) {
var subCookies = this.getAllName(name);
if(subCookies){
return subCookies[subName];
}else{
return null;
}
},
getAllName(name) {
var cookieName = encodeURIComponent(name) + "=",
cookieStart = document.cookie.indexOf(cookieName),
cookieEnd,
cookieArr,
result = {},
parts,
cookieValue = null;
if (cookieStart > -1) {
cookieEnd = document.cookie.indexOf(";", cookieStart);
if (cookieEnd == -1) {
cookieEnd = document.cookie.length;
}
cookieValue = document.cookie.substring(cookieStart +
cookieName.length, cookieEnd);
if (cookieValue.length > 0) {
cookieArr = cookieValue.split("&");
for (var i = 0; i < cookieArr.length; i++) {
parts = cookieArr[i].split("=");
result[decodeURIComponent(parts[0])] =
decodeURIComponent(parts[1]);
}
return result;
}
}
return null;
}
}
//假设
document.cookie = "data=name=Yujia&book=JavaScript&like=read";
subCookieUtil.getAllName("data")
//{name: "Yujia", book: "JavaScript", like: "read"}
subCookieUtil.get("data","book")
// JavaScript
虽然子
Cookie
能够解决单域名的上线,但是我们还是要注意cookie
的长度不要超出浏览器限制。