HTTP 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
Cookie: name=value
Other-header: other-header-value
发送回服务器的额外信息可以用于唯一验证客户来自于发送的哪个请求。
限制
cookie
在性质上是绑定在特定的域名下的。当设定了一个cookie
后,再给创建它的域名发送请求时,都会包含这个cookie
。这个限制确保了储存在cookie
中的信息只能让批准的接受者访问,而无法被其他域访问。
由于cookie
是存在客户端计算机上的,还加入了一些限制确保cookie
不会被恶意使用,同时蛇占有太多磁盘空间。每个域的cookie
总数是有限的,不过浏览器之间各有不同。
当超过单个域名限制之后还要设置cookie
,浏览器就会清楚以前设置的cookie
,IE
和Opera
会删除最近最少使用过的(LRU
,Least Recently Used
)cookie
。Firefox
看上去好像是随机决定要清楚哪个cookie
,所以考虑cookie
限制非常重要,以免出现不可预期的后果。
浏览器中对于cookie
的尺寸也有限制。大多数浏览器都有大约4096B(加减1)
的长度限制。为了最佳的浏览器兼容性,最好将整个cookie
长度限制在4095B
以内。尺寸限制影响到一个域下所有的cookie
,而并非每个cookie
单独限制。
如果尝试创建超过最大尺寸限制cookie
,那么该cookie
会被悄无声息的丢掉。注意,虽然一个字符通常占用一字节,但是多字节情况则有不同。
cookie的构成
cookie
由浏览器保存的以下几块信息构成。
- 名称:一个唯一确定
cookie
的名称。cookie
名称是不区分大小写的,所以myCookie
和MyCookie
被认为是同一个cookie
。然而,实践中最好将cookie
名称看作是区分大小写的,因为某些服务器会这样处理cookie
,cookie
的名称必须是经过URL
编码的。 - 值:储存在
cookie
里的字符串值。值必须被URL
编码。 - 域:
cookie
对哪个域是有效的。所有向该域发送的请求中都会包含这个cookie
信息。这个值可以包含子域,也可以不包含它。如果没有明确设定,那么这个域会被人做来自设置cookie
的那个域。 - 路径:对于指定域中的那个路径,应该向服务器发送
cookie
。例如,你可以指定cookie
只有从http://www.wrox.com/books/
中才能访问,那么http://www.wrox.com
的页面就不会发送cookie
信息,即使请求都是来自同一个域的。 - 失效时间:表示
cookie
何时应该被删除的时间戳(也就是,何时应该停止向服务器发送这个cookie
)。默认情况下,浏览器会话结束时即将所有cookie
删除;不过也可以自己设置删除时间。这个值是GMT
格式的日期,用于指定应该删除cookie
的精确时间。因此,cookie
可以在浏览器关闭后依然保存在用户的机器上。如果你设置的失效日期是个以前的时间,那么cookie
则会被立刻删除。 - 安全标志: 指定后,
cookie
只有在使用SSL
连接的时候才发送到服务器。
每一段信息都作为Set-Cookie
头的一部分,使用分号加空格分隔每一段,如下例所示。
HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value; expires=Mon, 22-Jan-07 07:10:24 GMT; domain=.wrox.com
Other-header: other-header-value
该头信息指定了一个叫做name
的cookie
,它会在格林威治时间2007年1月22日7:10:24失效,同时对于www.wrox.com
和wrox.com
的任何子域都有效。
secure
标志是cookie
中唯一一个非名值对儿的部分,直接包含一个secure
单词。如下:
HTTP/1.1 200 OK
Content-type: text/html
Set-cookie: name=value; domain=.wrox.com; path=/; secure
这里,创建了一个对于所有wrox.com
的子域和域名下(由path
参数指定的)所有页面都有效的cookie
,因为设置了secure
标志,这个cookie
只能通过SSL
连接才能传输。
尤其要注意,域、路径、失效时间和secure
标志都是服务器给浏览器的指示,以指定合适应该发送cookie
,这些参数并不会作为发送到服务器的cookie
信息的一部分,只有名值对儿才会被发送。
JS中的cookie
在JS中处理cookie
有些复杂,因为其众所周知的蹩脚接口,即BOM
的document.cookie
属性。这个属性的独特之处在于它会因为使用它的方式不同表现出不同的行为。当用来获取属性值时,document.cookie
返回当前页面可用的(根据cookie
的域、路径、失效时间和安全设置)所有cookie
字符串,一系列由分号隔开的名值对儿,如下所示。
name1 = value1; name2 = value2; name3 = value3;
所有名字和值都是经过URL
编码的,所以必须使用decodeURIComponent()
来解码。
当用于设置值得时候,document.cookie
属性可以设置为一个新的cookie
字符串。这个cookie
字符串会被解释并添加到现有的cookie
集合中。设置document.cookie
并不会覆盖cookie
,除非设置的cookie
的名称已经存在。设置cookie
的格式如下,和Set-Cookie
头中使用的格式一样。
name = value; expires = expiration_time; path = domain_path; domain = domain_name; secure
这些参数中,只有cookie
的名字和值是必需的,下面是一个简单的例子。
document.cookie = 'name = Ann';
这段代码创建了一个叫name
的cookie
,值为Ann
。当客户端每次向服务器端发送请求的时候,都会发送这个cookie
,当浏览器关闭的时候,它就会被删除。虽然这段代码没问题,但因为这里恰好名称和值都无需编码,所以最好每次设置cookie
时都使用encodeURIComponent()
。
document.cookie = encodeURIComponent('name') + '=' + encodeURIComponent('Ann');
要给被创建的cookie
指定额外的信息,只要将参数追加到该字符串,和Set-Cookie
头中的格式一样,如下所示。
document.cookie = encodeURIComponent('name') + '=' + encodeURIComponent('Ann') + '; domain=.wrox.com; path=/';
HTTP专有cookie
还有一类cookie
被称为“HTTP
专有cookie
”。HTTP
专有cookie
可以从浏览器或者服务器设置,但是只能从服务器端读取,因为JS无法获取HTTP
专有cookie
的值。
由于所有的cookie
都会由浏览器作为请求头发送,所以在cookie
中存储大量信息会影响到特定域的请求性能。cookie
信息越大,完成对服务器请求的时间也就越长。尽管浏览器对cookie
进行了大小限制。不过最好还是尽可能在cookie
中少存储信息,以避免影响性能。
Tips
一定不要在cookie
中存储重要和敏感的数据。cookie
数据并非存储在一个安全环境中,其中包含的任何数据都可以被他人访问。所以不要在cookie
总存储如信用卡号或者个人地址之类的数据。