《HTTP权威指南》笔记:第十一章-客户端识别与cookie机制

一、个性化

HTTP最初是一个匿名,无状态的 请求/响应 协议,Web服务器几乎没有什么信息可以用来判定是哪一个用户发来的请求,后来开发者们总结了一些识别机制来标识用户:

  1. 包含用户信息的HTTP首部
  2. 通过客户的IP地址来识别
  3. 用认证的方式识别
  4. URL,把用户信息嵌入在URL

二、通过首部识别

以下是常见用来承载用户相关的HTTP请求首部:

  • from,用户的邮箱地址
  • user-agent,用户的浏览器软件
  • referer,请求来自的页面
  • authorization,用户名和密码
  • client-ip,客户端ip地址(扩展)
  • x-forwarded-for,客户端ip地址(扩展)
  • cookie,用户标识

一般来说,没有浏览器或者用户会使用from,因为担心邮箱泄露导致大量的垃圾邮件,这个头部一般用于正规爬虫。user-agent可以告诉服务端请求来自何种服务器,实现与浏览器相关的定制内容返回。referer这个首部也不可靠,因为可以手动伪造(有的浏览器会禁止修改这个首部)。

三、客户端IP地址

web浏览器可以找到承载HTTP请求的tcp连接对应的目的ip,但是用ip来标识客户并不可靠,主要有以下原因:

  1. ip描述的是机器而非用户
  2. ip一般由服务商动态分配
  3. ip地址是有限的,所以很多用户是通过NAT接入网络的
  4. 有时只能获取到代理的ip而非客户端的

四、用户登录

首先服务端返回错误码401 login required,此时浏览器弹出登录对话框,用户输入并确认后浏览器会把用户的信息放在authorization首部中发送给服务端,并且会保存下来,之后每次请求都会带上该首部。这样做的好处是用户只需要登录一次,并且相对可靠。缺点是不安全,把用户名密码直接放在首部很容易被其他观察者直接看到并泄露。

五、胖URL

有的网站会为每个用户生成特殊的识别码并嵌入url中,并以此来标识用户,而且还可以在url中追加一些用户状态等等,这样做对用户来说很方便,几乎无感知,因为主要通过服务端重写url来完成,但是缺点也很多:

  1. 过长的url
  2. 无法共享连接,因为你的连接中包含你的个人信息
  3. 无法缓存,因为缓存是和url相关的,如果每个人的url都不相同,那么缓存就失效了
  4. 加重服务器负载
  5. 不稳定,如果用户在该页面已经操作了很多内容,一旦用户丢失了该连接,那么将永远无法找到

六、cookie

cookie是目前实现持久会话的最好的方式,现在所有主流浏览器都支持。

6.1 cookie的类型

我们可以吧cookie大致分为2类:会话cookie和持久cookie。会话cookie在关闭页面后就会失效,而持久cookie即使关闭页面也能保存一定时间。

6.2 客户端侧状态

cookie的基本思想是让浏览器积累一组服务器特有的信息,每次访问服务器时提供这些信息,因为信息是存储在客户端的,所以此系统被称为客户端侧状态。

6.3 不同的站点使用不同的cookie

浏览器内部存有很多的cookie,但是不会在访问网站的时候带上所有的cookie,因为cookie只是一些键值对,只对设置这些cookie`的网站有效,对其他人来说都是不可读的垃圾数据。

6.3.1 cookie的域属性

set-cookie可以给响应首部添加一个domain属性来控制那些站点可以使用该cookie

set-cookie: user="sadhgiaq3124jaklh"; domain="xxx.com"

6.3.2 cookie的path属性

除了设置域,还可以设置path,这样可以减少无用cookie传播,只有访问特定的path才会携带该cookie

set-cookie: pref="color"; domain="xxx.com"; path="/pages/"

如果设置了以上2个cookie,访问www.xxx.com时携带:

cookie:user="sadhgiaq3124jaklh";

访问www.xxx.com/pages/index.html时携带:

cookie:user="sadhgiaq3124jaklh";pref="color"

6.4 cookie的组成

目前使用的cookie有2个版本:版本0和版本1,后者是前者的扩展,但应用不及前者广泛

6.4.1 版本0(Netscape)

set-cookie首部:

  • name=value,必须的
  • expires=date,可选的,指定cookie过期时间
  • domain=value,可选的,设置cookie指定域,如果没有设置,那么默认为当前主机名
  • path=value,可选的,指定路径,如果没设置,那么默认当前路径
  • secure,可选的,如果包含这个属性,那么只有在https连接中才会携带该cookie

使用set-cookie设置的cookie在请求时会被合并到一个cookie首部中。

6.4.2 版本1(RFC2965)

RFC2109定义了一个cookie的扩展版本,引入了set-cookie2cookie2首部,下面是set-cookie2的可用首部:

  • name=value,必须的,同版本0
  • version,必须的,一个整数,set-cookie2:version= "1"
  • comment,可选的,说明服务器如何使用该cookie
  • comment-url,可选的,提供一个url指针,指向的文档详细说明cookie使用文档
  • discard,可选的,表示当前cookie为会话cookie,会话结束后直接销毁
  • domain,同版本0
  • max-age,可选的,相对过期时间
  • path,可选的,同版本0
  • port,可选的,只能向指定端口提供cookie
  • secure,同版本0

该规范的cookie2首部里所有关键字都以$开头。

6.4.3 版本协商

因为版本1的cookie扩展功能更多,所以当请求链路上的设备都支持版本1的话,那应该使用版本1,下面描述各设备之间如何协商cookie版本:

  1. 服务器响应请求时会发送set-cookieset-cookie2,客户端如果支持版本1cookie,那么会丢弃set-cookie的值
  2. 如果服务端未使用set-cookie2,客户端可以发送cookie2: $version=1告知服务端可以使用set-cookie2

6.5 cookie与缓存

当公共缓存缓存带有set-cookie的响应时应该格外小心,下面是一些处理缓存需要注意的规则:

  1. 如果该文档可以缓存,但是不希望缓存set-cookie首部,服务器应道注明cache-control:no-cache="set-cookie"
  2. 当服务端通过某个请求去设置cookie的时候,需要让这个请求使用协商缓存,即每一个请求必须到达服务器,否则当代理缓存中有该请求的缓存,那么其他客户端就无法获得cookie。有些比较严格的代理会舍弃一切带有set-cookie首部的副本。
  3. 当服务端接收到带有cookie的请求时一定要注意,这个响应可能是私有的,那么服务端应该设置好响应首部避免该响应被公共缓存保存。

参考资料

[1]《HTTP权威指南》

你可能感兴趣的:(《HTTP权威指南》笔记:第十一章-客户端识别与cookie机制)