HTTP(五):会话跟踪

简述

参考:RFC2109 RFC6256

HTTP Cookie(也叫Web cookie或者浏览器Cookie)是服务器发送到用户浏览器并保存在浏览器上的一块数据,它会在浏览器下一次发起请求时被携带并发送到服务器上。比较经典的,可以它用来确定两次请求是否来自于同一个浏览器,从而能够确认和保持用户的登录状态。Cookie的使用使得基于无状态的HTTP协议上记录稳定的状态信息成为了可能。

一、Cookie

参考:HTTP Cookie

1.1 用途

  • 会话状态管理(如用户登录状态、购物车)
  • 个性化设置(如用户自定义设置)
  • 浏览器行为跟踪(如跟踪分析用户行为)

因为HTTP协议是无状态的,即服务器不知道用户上一次做了什么,这严重阻碍了交互式Web应用程序的实现。在典型的网上购物场景中,用户浏览了几个页面,买了一盒饼干和两饮料。最后结帐时,由于HTTP的无状态性,不通过额外的手段,服务器并不知道用户到底买了什么。 所以Cookie就是用来绕开HTTP的无状态性的“额外手段”之一。服务器可以设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态。

在刚才的购物场景中,当用户选购了第一项商品,服务器在向用户发送网页的同时,还发送了一段Cookie,记录着那项商品的信息。当用户访问另一个页面,浏览器会把Cookie发送给服务器,于是服务器知道他之前选购了什么。用户继续选购饮料,服务器就在原来那段Cookie里追加新的商品信息。结帐时,服务器读取发送来的Cookie就行了。

Cookie另一个典型的应用是当登录一个网站时,网站往往会请求用户输入用户名和密码,并且用户可以勾选“下次自动登录”。如果勾选了,那么下次访问同一网站时,用户会发现没输入用户名和密码就已经登录了。这正是因为前一次登录时,服务器发送了包含登录凭据(用户名加密码的某种加密形式)的Cookie到用户的硬盘上。第二次登录时,(如果该Cookie尚未到期)浏览器会发送该Cookie,服务器验证凭据,于是不必输入用户名和密码就让用户登录了。

1.2 工作原理

  1. 第一次请求,客户端发送把username\password或购物车等信息放入报文的实体部分,通常是以 POST 方法把请求发送给服务器。
  2. 服务器收到请求,响应后返回识别该用户的的 Session ID。通过验证从客户端发送过来的登录信息进行身份验证,然后把用户的认证状态与 Session ID 绑定后记录在服务器端。向客户端返回响应时,会在首部字段 Set-Cookie 内写入 Session ID。
  3. 客户端接收到从服务器端发来的 Session ID 后,以 Cookie 存在本地。下次向服务器发送请求时,浏览器会自动发送 Cookie,并且 Session ID 也随之发送到服务器。服务器端可通过验证接收到的 Session ID 识别用户和其认证状态。

下面是一个登录的完整过程技术实现:

1.3 创建Cookie

当服务器收到HTTP请求时,可以在响应头里面增加一个Set-Cookie头部。浏览器收到响应之后会取出Cookie信息并保存,之后对该服务器每一次请求中都通过Cookie请求头部将Cookie信息发送给服务器。另外,Cookie的过期时间、域、路径、有效期、站点都可以根据需要来指定。

一个简单的Cookie可能像这样:

1
Set-Cookie: <cookie名称>=<cookie值>

服务器某次返回的Cookie,如:

1
2
3
4
5
6
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry

[页面内容]

那么下次客户端请求时:

1
2
3
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry

Set-Cookie 其他字段的属性:

属性 说明
NAME=VALUE 赋予 Cookie 的名称和其值(必须项)
expires=DATE Cookie 的有效期(若不明确指定则默认为浏览器关闭前为止)
path=PATH Cookie的作用域,指定服务器匹配Cookie的文件目录, 子文件夹也会被匹配到
domain=域名 需要发送Cookie的主机名。 如果没有指定,默认为当前的文档地址上的主机名(但是不包含子域名)。如果指定了Domain,则一般包含子域名。
Secure 仅在 HTTPS 安全通信时才会发送 Cookie
HttpOnly HTTP-only类型的Cookie不能使用Javascript通过Document.cookie属性来访问,从而能够在一定程度上阻止跨域脚本攻击(XSS

1.4 Cookie类型

1.4.1 持久型Cookie

持久Cookie可以指定一个特定的过期时间(Expires)或者有效期(Max-Age)。

1
Set-Cookie: status=enable; expires= Tue, 05 Apr 2017 07:26:31 GMT; path=/; domain=.explame.com;

1.4.2 非持久性Cookie

也称Session Cookie,Session Cookie是最简单的Cookie:浏览器关闭之后它会被自动删除,也就是它仅在会话期间有效。会话期Cookie不需要指定过期时间(Expires)或者有效期(Max-Age)。需注意的是,有些浏览器提供了会话恢复的功能,这种情况下即便关闭了浏览器会话期Cookie也会被保存,就好像浏览器从来没有关闭一样。

1.5 缺陷

  1. Cookie会被附加在每个HTTP请求中,所以无形中增加了流量。
  2. 由于在HTTP请求中的Cookie是明文传递的,所以安全性成问题。(除非用HTTPS)
  3. Cookie的大小限制在4KB左右。对于复杂的存储需求来说是不够用的。

1.6 Cookie实例

二、Session

上面Cookie原理中,登录的过程,就说明了Session存储在服务器,并从Cookie中的session id来进行跟踪、关联某一用户的信息、行为等。

Session是在服务端保存的一个数据结构,有一个唯一标识,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中。集群的时候也要考虑Session的转移,在大型的网站,一般会有专门的Session服务器集群,用来保存用户会话,这个时候 Session 信息都是放在内存的,使用一些缓存服务比如Memcached之类的来放 Session。

Session基本上,每一次浏览器请求时,都会生成一个新的,当然,在浏览器开多的tab时,一般会共用一个Session。

Session的删除,取决于服务器端对Session的机制,而不跟浏览器相关,浏览器关闭并不会导致Session删除,只能影响本地的Cookie。

Session在Cookie被禁止的情况下,有一种代替机制:URL重写。

三、URL重写

把session id直接附加在URL路径的后面,附加方式也有两种。

  • 作为URL路径的附加信息,表现形式为 http://...../xxx**;sessionid=123456
  • 作为查询字符串附加在URL后面,表现形式为http://...../xxx?sessionid=123456

两种方式对用户都是透明的,区别在于服务器的处理方式上。

第一种方式可以session id的信息和正常程序参数区分开来。 但是在整个网络交互过程中,需要浏览器始终添加session id。

另一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。