全面解读HTTP Cookie

Cookie机制

Cookie技术是客户端的解决方案,Cookie就是由服务器发给客户端的特殊信息,而这些信息以文本的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息。

让我们说得更具体一些:当用户使用浏览器访问一个支持Cookie的网站的时候,用户会提供包括用户名在内的个人信息并且提交至服务器;接着,服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,当然这些信息并不是存放在HTTP响应体(Response Body)中的,而是存放于HTTP响应头(Response Header);当客户端浏览器接收到来自服务器的响应之后,浏览器会将这些信息存放在一个统一的位置,对于Windows操作系统而言,我们可以从: [系统盘]:Documents and Settings[用户名]Cookies目录中找到存储的Cookie;自此,客户端再向服务器发送请求的时候,都会把相应的Cookie再次发回至服务器。而这次,Cookie信息则存放在HTTP请求头(Request Header)了。

有了Cookie这样的技术实现,服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的Cookie得到客户端特有的信息,从而动态生成与该客户端相对应的内容。通常,我们可以从很多网站的登录界面中看到“请记住我”这样的选项,如果你勾选了它之后再登录,那么在下一次访问该网站的时候就不需要进行重复而繁琐的登录动作了,而这个功能就是通过Cookie实现的。

在程序中,会话跟踪是很重要的事情。理论上,一个用户的所有请求操作都应该属于同一个会话,而另一个用户的所有请求操作则应该属于另一个会话,二者不能混淆。例如,用户A在超市购买的任何商品都应该放在A的购物车内,不论是用户A什么时间购买的,这都是属于同一个会话的,不能放入用户B或用户C的购物车内,这不属于同一个会话。

而Web应用程序是使用HTTP协议传输数据的。HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。即用户A购买了一件商品放入购物车内,当再次购买商品时服务器已经无法判断该购买行为是属于用户A的会话还是用户B的会话了。要跟踪该会话,必须引入一种机制。

Cookie就是这样的一种机制。它可以弥补HTTP协议无状态的不足。在Session出现之前,基本上所有的网站都采用Cookie来跟踪会话。

如果你把Cookies看成为http协议的一个扩展的话,理解起来就容易的多了,其实本质上cookies就是http的一个扩展。有两个http头部是专门负责设置以及发送cookie的,它们分别是Set-Cookie以及Cookie。当服务器返回给客户端一个http响应信息时,其中如果包含Set-Cookie这个头部时,意思就是指示客户端建立一个cookie,并且在后续的http请求中自动发送这个cookie到服务器端,直到这个cookie过期。如果cookie的生存时间是整个会话期间的话,那么浏览器会将cookie保存在内存中,浏览器关闭时就会自动清除这个cookie。另外一种情况就是保存在客户端的硬盘中,浏览器关闭的话,该cookie也不会被清除,下次打开浏览器访问对应网站时,这个cookie就会自动再次发送到服务器端。一个cookie的设置以及发送过程分为以下四步:

  • 客户端发送一个http请求到服务器端
  • 服务器端发送一个http响应到客户端,其中包含Set-Cookie头部
  • 客户端发送一个http请求到服务器端,其中包含Cookie头部
  • 服务器端发送一个http响应到客户端

这个通讯过程也可以用以下下示意图来描述:

《全面解读HTTP Cookie》

在客户端的第二次请求中包含的Cookie头部中,提供给了服务器端可以用来唯一标识客户端身份的信息。这时,服务器端也就可以判断客户端是否启用了cookies。

Cookie 的属性

Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]

上面的Set-Cookie字段,用分号分隔多个属性。它们的含义如下。

value 属性

value属性是必需的,它是一个键值对,用于指定Cookie的值。

expires 属性

expires属性用于指定 Cookie 过期时间。它的格式采用Date.toUTCString()的格式。

如果不设置该属性,或者设为null,Cookie只在当前会话(session)有效,浏览器窗口一旦关闭,当前 Session 结束,该 Cookie 就会被删除。

浏览器根据本地时间,决定 Cookie 是否过期,由于本地时间是不精确的,所以没有办法保证 Cookie 一定会在服务器指定的时间过期。

domain属性

domain属性指定 Cookie 所在的域名,比如example.com或.example.com(这种写法将对所有子域名生效)、subdomain.example.com。

如果未指定,默认为设定该Cookie的域名。所指定的域名必须是当前发送Cookie的域名的一部分,比如当前访问的域名是example.com,就不能将其设为google.com。只有访问的域名匹配 domain 属性,Cookie 才会发送到服务器。

path 属性

path属性用来指定路径,必须是绝对路径(比如/、/mydir),如果未指定,默认为请求该 Cookie 的网页路径。

只有path属性匹配向服务器发送的路径,Cookie 才会发送。这里的匹配不是绝对匹配,而是从根路径开始,只要path属性匹配发送路径的一部分,就可以发送。比如,path属性等于/blog,则发送路径是/blog或者/blog/roll,Cookie都会发送。path属性生效的前提是domain属性匹配。

secure 属性

secure属性用来指定Cookie只能在加密协议HTTPS下发送到服务器。

该属性只是一个开关,不需要指定值。如果通信是HTTPS协议,该开关自动打开。

max-age

max-age属性用来指定Cookie有效期,比如60 60 24 * 365(即一年31536e3秒)。

HttpOnly

HttpOnly属性用于设置该Cookie不能被JavaScript读取。

修改与删除

修改

要想修改一个cookie,只需要重新赋值就行,旧的值会被新的值覆盖。但要注意一点,在设置新cookie时,Cookie的key、domain、path和secure与旧的必须匹配。否则不会修改旧值,而是添加了一个新的 cookie。

Set-Cookie: key1=value1; domain=example.com; path=/blog

改变上面这个 Cookie 的值,就必须使用同样的Set-Cookie。

Set-Cookie: key1=value2; domain=example.com; path=/blog

只要有一个属性不同,就会生成一个全新的 Cookie,而不是替换掉原来那个 Cookie。

Set-Cookie: key1=value2; domain=example.com; path=/

上面的命令设置了一个全新的同名 Cookie,但是path属性不一样。下一次访问example.com/blog的时候,浏览器将向服务器发送两个同名的 Cookie。

Cookie: key1=value1; key1=value2

上面代码的两个 Cookie 是同名的,匹配越精确的Cookie排在越前面。

删除

删除一个 Cookie 的唯一方法是设置其expires为一个过去的日期。

document.cookie = 'fontSize=;expires=Thu, 01-Jan-1970 00:00:01 GMT';

上面代码中,名为fontSize的 Cookie 的值为空,过期时间设为1970年1月1月零点,就等同于删除了这个 Cookie。

    原文作者:HTTP
    原文地址: https://segmentfault.com/a/1190000012455531
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞