数据缓存方案一:Cookie

2019-04-27  本文已影响0人  萘小蒽

很多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的长度不要超出浏览器限制。

上一篇下一篇

猜你喜欢

热点阅读