Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cookie 知多少 #11

Open
fwon opened this issue Aug 13, 2014 · 2 comments
Open

Cookie 知多少 #11

fwon opened this issue Aug 13, 2014 · 2 comments

Comments

@fwon
Copy link
Owner

fwon commented Aug 13, 2014

问题由来

Web服务器可能会同时与数千个不同的客户端进行对话,这些服务器通常要记录下它们与谁交流,而不会认为所有的请求都来自匿名的客户端,那有哪些技巧可以让服务器识别到不同的客户端呢。

我们知道HTTP是一个无连接,无状态的请求/响应协议。
【无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。】
Web服务器几乎没有什么信息可以用来判定是哪个用户发送的请求,也无法记录来访用户的请求序列。

解决方案

  • 承载用户身份的HTTP首部。
  • 客户端IP地址跟踪,通过用户的IP地址对其进行识别。
  • 用户登录,用认证方式来识别用户。
  • 胖URL,一种在URL中嵌入识别信息的技术。
  • cookie,一种功能强大且高效的持久身份识别技术。

下面主要就cookie的实现方式展开,如果对上述方法也有兴趣的可以参考《HTTP权威指南》

cookie

1. cookie的分类类
cookie分为会话cookie持久cookie。会话cookie是一种临时的cookie,它记录了用户访问站点时的设置和偏好。用户退出浏览器时,会话cookie就被删除了,持久cookie的生存时间更长一些;它们存储在硬盘上。通常会用持久cookie来维护某个用户周期性访问站点的登录信息。

会话cookie和持久cookie之间唯一的区别就是他们的过期时间。如果设置了Discard参数,或者没有设置Expires或Max-Age参数来说明扩展的过期时间,这个cookie就是一个会话cookie。

2. cookie工作原理
用户首次访问Web站点是,Web服务器对用户一无所知。服务器返回信息给用户时,就包含了一个cookie,用户下次访问站点时,就会携带此cookie,这时候Web服务器就能识别此客户端了。
cookie中包含了一个由name=value信息构成的任意列表,并通过Set-Cookie或Set-Cookie2 HTTP响应首部将其贴到用户身上去。
roadmap.path
cookie中可以包含任意信息,它们通常都只包含一个服务器为了进行跟踪而产生的独特识别码,比如id="34294"。服务器可以用这个数字来查找服务器为其访问者积累的数据库信息(用户购物地址,地址信息等)。

浏览器会记住从服务器返回的Set-Cookie或Set-Cookie2首部中的cookie内容,并将cookie集存储在浏览器的cookie数据库中。并在下次访问时在一个cookie请求首部中将其传出去。

3. 几个重要的cookie属性
cookie的域属性---domain
产生cookie的服务器可以像Set-Cookie响应首部添加一个Domain属性来控制哪些站点可以看到那个cookie。

cookie的路径属性---path
通过Path属性可以讲cookie与部分Web站点关联起来。例如,某个Web服务器可能由两个组织共享的,每个组织都有独立的cookie。比如站点www.airtravel.com可能会将部分Web站点用于汽车租赁--比如,www.airtravel.com/autos/用一个独立的cookie来记录用户喜欢的汽车尺寸,可能会生成一个如下所示的特殊汽车租赁cookie:

Set-cookie:pref=compact;domain="airtravel.com";path=/autos/

如果用户访问www.airtravel.com/specials.html,就只会获得这个cookie:

Cookie:user="mary17"

但如果访问www.airtravel.com/autos/cheapo/index.html,就会获得这两个cookie:

Cookie: user="mary17"
Cookie: pref="compact"

4. Cookie的版本
cookie规范有两个不同的版本,cookie版本0(有时候被称为Netscape cookies)和cookies版本1(RFC 2965)。cookie版本1是对cookies版本0的扩展,应用不如后者广泛。
cookie版本0(Netscape)
最初的cookie规范是由网景公司定义的。这些"版本0"的cookie定义了Set-Cookie响应首部,cookie请求首部以及用于控制cookie的字段。版本0的cookie看起来如下所示:
Set-Cookie:name=value[;expires=date][;path=path][;domain=domain][;secure]
Cookie:name1=value1[;name2=value2]...

cookie版本1(RFC 2965)
RFC 2965定义了一个cookie的扩展版本。这个版本1标准引入了Set-Cookie2首部和Cookie2首部,但它也能与版本0系统进行互操作。

RFC2965Cookie的主要改动包括下列内容:

  • 为每个Cookie关联上解释性文本,对其目的进行解释。
  • 允许在浏览器退出时,不考虑过期时间,将Cookie强制销毁。
  • 用相对秒数,而不是绝对日期来表示Cookie的Max-Age。
  • 通过URL端口号,而不仅仅是域和路径来控制Cookie的能力。
  • 通过Cookie首部回送域,端口和路径过滤器。
  • 为实现互操作性使用的版本号。
  • 在Cookie首部从名字中区分出附加关键字的$前缀。

如果客户端从同一个响应中既获得了Set-Cookie首部,又获得了Set-Cookie2首部,就会忽略老的Set-Cookie首部。如果客户端既支持版本0又支持版本1的cookie,但从服务器获得的是版本0的Set-Cookie首部,就会带着版本0的Set-Cookie首部发送cookie。但客户端还应该发送Cookie2:$Version="1"来告知服务器它是可以升级的。

Cookie的安全性
cookie被用来做的最多的一件事就是保持身份认证的服务端状态。这种保持可能是基于会话的(Session),也有可能是持久性的。所以cookie中包含的服务端信息一旦泄露,那么就有可能造成用户信息被盗的危险。为了安全考虑,通常我们会禁止js直接对Cookie进行操作。通过给Cookie加上HttpOnly标签。浏览器的document就看不到Cookie了。能有效防止简单的页面XSS攻击。

对已Cookie的安全防范包括与Session的配合使用将会在后面再做总结。

@DeanThompson
Copy link

HTTP 1.1 支持 keepalive,一个连接可以用于多次请求,减少频繁建立和关闭连接的开销。

@fwon
Copy link
Owner Author

fwon commented Sep 28, 2014

@DeanThompson keepalive是默认开启的,只能减少握手产生的开销;对于静态文件,cookie的传送仍然是多余的。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants