cookie

###服务器响应头
HTTP/1.1 200 OK Content-Type: text/html Set-Cookie: name=value Other-header: other-header-value

###HTTP头信息发送回服务器
GET /index.html HTTP/1.1 Cookie: name=value Other-header: other-header-value
##限制
- 每个域cookie数量有限
- 超过单个域名限制后浏览器, 清除以前设置的cookie
- cookie尺寸限制在4095字节以内

##cookie成分

cookie由浏览器保存的一下几块信息组成

  • 名称:唯一确定cookie的名称,大小写不敏感,必须经过URL编码
  • :存储在cookie中的字符串值,必须经过URL编码
  • :cookie对于哪个域有效,所有该域的请求都包含这个cookie
  • 路径:对于指定域的哪个路径,应该向服务器发送cookie
  • 失效事件:表示cookie合适应该被删除的事件
  • 安全标识:指定后的cookie只有在SSL连接时才发送服务器

每段信息作为Set-Cookie头的一部分

HTTP/1.1 200 OK
Content-Type: text/html
       Set-Cookie: name=value; expores=Mon, 22-Jan-07 07:10:24 GMT; domain=.wrox.com; path=/; secure
Other-header: other-header-value

该头信息指定了一个叫做name的cookie,它会在格林威治事件2007年1月22日7:10:24失效,同时对于www.wrox.com和wrox.com的子域名都有效(由path参数指定的)。、

注意:
只有名-值对才会发送到服务器。
域、路径、失效时间和secure标识都是服务器给浏览器都只是,以何时发送cookie,这些参数不会发送到服务器的cookie信息的一部分。

##JavaSctipt中的cookie

JavaScript处理cookie用BOM的document.cookie, 返回当前可用页面的所有字符串,一系列由分号隔开的名-值对,如下实例。

name1=value1;name2=value2;name3=value3

document.cookie也可以设置新的字符串, 设置cookie的格式巨额Set-Cookie头使用一样的格式:

name1=value; expires=exporation_time; path=domain_path; domain=domain_name; secure

这些参数中只有cookie的名值对是必须的,下面是一个简单的例子。

document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Nicholas");

也可以添加指定的额外信息

document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Nicholas") + "; domain=.wrox.com; path=/";

由于JavaScript中读写cookie不直观,我们常常写一些函数简化cookie功能。基本的cookie操作有三种:读取、写入和删除。

它们在CookieUtil对象如下表示:

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) {
                var cookieEnd = document.cookie.length;
            }
            cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));
        }
        return cookieValue;
    },

    set: function(name, value, expires, path, domain, secure) {
        var cookieText = encodeURICompnet(name) + "=" + encodeURICompnet(value);

        if (expires instanceof Data) {
            cookieText += "; expires=" + expires.toGMTString();
        }

        if (path) {
            cookieText += "; domain=" + domain;
        }

        if (secure) {
            cookieText += "; secure";
        }

        document.cookie = cookieText;
    },

    unset: funciton (name, path, domain, secure) {
        this.set(name, "", new Data(0), path, domain, secure);
    }
};

这些方法可以如下使用:

//设置cookie
CookieUtil.set("name", "Nicholas");
CookieUtil.set("book", "Professional JavaScript");

//读值
alert(CookieUtil.get("name");    //"Nicholas"
alert(CookieUtil.get("book");    //"Professional JavaScript"

//删除cookie
CookieUtil.unset("name");
CookieUtil.unset("book");

//设置一个cookie,包括它的路径、域、截止日期
CookieUtil.set("name", "Nicholas", "/book/projs/", "www.wrox.com", new Data("Javuary 1, 2010"));

//删除同一cookie
CookieUtil.unset("name", "/book/projs/", "www.wrxo.com");

//设置一个安全的cookie
CookieUtil.set("name", "Nicholas", null, null, null, true);

## 子 cookie
绕开浏览器单域名下的cookie数限制,是存放在单个cookie中的更小段的数据,也就是使用cookie值来存取多个名-值对。

常见格式如下:

name=name1=value1&name2=value2&name3=value3&name4=value4&name5=value5

为了更好地操作子cookie,必须建立一系列新方法。

例如,要获得一个子cookie,需要遵循与获得cookie一样的基本步骤,但是在解码cookie值之前,需要如下找出子cookie的信息:

var SubCookieUtil = {

    get: funciton (namek, subName) {
        var subCookies = this.getAll(name);
        if (subCookies) {
            return subCookies[subName];
        } else {
            return null;
        }
    },

    getAll: function(name) {
        var cookieName = encodeURIComponent(name) + "=",
            cookieStart = document.cookie.indexOf(cookieName),
            cookieValue = null,
            result = {};

        if (cookieStart > -1) {
            var cookieEnd = document.cookie.indexOf(";", cookieStart);
            if (cookieEnd == -1) {
                cookieEnd = document.cookie.length;
            }
            cookieValue = document.cookie.substring(cookieStart + cookieName.length, cookieEnd);

            if (cookieValue.length > 0) {
                var subCookies = cookieValue.split("&");

                for (var i = 0, len = subCookies.length; i < len; i++) {
                    var parts = subCookies[i].split("=");
                    result[decondeURIComponent(parts[0])] = decondeURIComponent(parts[1]);
                }

                return result;
            }
        }

            return null;
    },

        //此处更多代码
};

这些方法如下使用:

//假设document.cookie=data=name=Nicholas&book=Professional%20JavaScript

//获取全部子cookie
var data = SubCookieUtil.getAll("data");
alert(data.name);    //"Nicholas"
alert(data.book);    //"Professional JavaScript"

//逐个获取子cookie
alert(SubCookieUtil.getAll("data", "name"));    //"Nicholas"
alett(SubCookieUtil.getAll("data", "book"));    //"Professional JavaScript"

要设置子Cookie,也有两种方法:set()和setAll().以下代码展示它们的构造:

var SubCookieUtil = {
    set: function(name, subName, value, expires, path, domain, secure) {
        //"||"用于当getAll()返回null时将subcookies设置为一个新对象
        var subcookies = this.getAll(name) || {};
        subcookieutil[subName] = value;
        this.setAll(name, subcookies, expires, path, domain, secure);
    },

    setAll: function(name, subcookies, expires, path, domain, secure) {

        var cookieText = encodeURIComponent(name) + "=";
        var subcookiesParts = new Array();

        for (var subName in subcookies) {
            if (subName.length > 0 && subCookies.hasOwnProperty(subName)) {
                subcookiesParts.push(encodeURIComponent(subName) + "=" + encodeURIComponent(subcookies[subName]));
            }
        }

        if (cookieParts.length > 0) {
            cookieText += subcookiesParts.join("&");

            if (expires instanceof Date) {
                cookieText += "; expores=" + expires.toGMTString();
            }

            if (path) {
                cookieText += "; path" + path;
            }

            if (domain) {
                cookieText += "; domain=" + domain;
            }

            if (secure) {
                cookieText += "; secure";
            }
        } else {
            cookieText += "; expores=" + (new Date(0)).toGMTString();
        }

        document.cookie = cookieText;
    },

    //此处更多代码
};

可以按如下方式使用这些方法:

//假设document.cookie=data=name=Nicholas & book=Professional%20JavaScipt

//设置2个cookie
SubCookieUtil.set("data", "name", "Nicholas");
SubCookieUtil.set("data", " book ", "Professional JavaScipt");

//设置全部子cookie和失效日期
SubCookieUtil.setAll("data", { name: "Nicholas", book: "Professional JavaScipt" }, new Data("January 1, 2010"));

//修改名字的值,并修改cookie的失效时间
SubCookieUtil.set("data", "name", "Michael", new Date("February 1, 2010") );

子cookie最后一组方法用于删除子cookie的。

普通cookie可以通过将失效时间设置为过去的时间的方法来删除,子cookie必须获取包含在某个cookie中的所有子cookie,

然后仅删除需要删除的那个子cookie,然后再将包含余下的子cookie值存为cookie的值

var SubCookieUtil = {
    
    //此处更多代码

    unset: function(name, subName, path, domain, secure) {
        var subcookies = this.getAll(name);
        if (subcookies) {
            delete subcookies[subName];
            this.setAll(name, subcookies, null, path, domain, secure);
        }
    },

    unsetAll: function(name, path, domain, secure) {
        this.setAll(name, null, mew Date(0), pathk, domain, secure)'
    }

};

这两个方法这样使用:

//仅删除名为name的子cookie
SubCookieUtil.unset("data", "name");

//删除整个cookie
SubCookieUtil.unsetAll("data");

##关于 cookie 的思考
还有一类称为HTTP专有的cookie, 只能从服务器端读取,JavaScript无法获得。

由于cookie都由浏览器作为请求放松,若存储大量信息会影响请求性能,最好尽可能少存储信息。

cookie的性能和它的局限性不能最为大量信息存储的方式。

Loading Disqus comments...
Table of Contents