Session 和 Cookie 的概念

网站通过 Session 和 Cookie 的机制记录访问者的一些基本信息,本小节依次讲解 Cookie 和 Session 的概念,并讲解了如何使用 Cookie 实现 Session。

1. 需求的提出

网站常常需要记录访问者的一些基本信息,例如:用户是否登录、用户登录名称、密码、用户在 Web 站点购物的方式或用户访问该站点的次数。

举个例子,用户在没有登陆 baidu 时,此时用户的身份是游客,baidu 首页的界面如下图所示:

图片描述

当用户登陆 baidu 页面后,此时用户的身份是已登录用户,可以看到页面的右上角显示了用户的名称,如下图所示:

图片描述

可以看出,baidu 服务端能够辨别用户的身份,根据用户是否登录显示不同的内容。如果用户的身份是游客,则显示文本登陆;如果用法的身份是已登录用户,则显示用户的名称。

网站为了辨别用户身份、进行会话跟踪需要把一些数据 (例如:登录状态、用户名称) 储存在用户本地终端上,这些数据被称为 Cookie

以登录 baidu 为例子,用户在没有登陆 baidu 时,访问的网页 URL 是 https://www.baidu.com;在登陆 baidu 后,访问的网页 URL 仍然是 https://www.baidu.com访问的页面 URL 相同,但是这两次访问呈现的结果不相同,登陆前没有显示用户名,登陆后显示了用户名。

服务端是通过 Cookie 的技术区分这两次请求的,如下图所示:

图片描述

  1. 用户登陆 baidu
  2. baidu 服务端会生成一个用户 ID
  3. baidu 服务端将这个用户 ID 发送给浏览器
  4. 浏览器收到这个用户 ID 后,会将这个用户 ID 保存在用户本地终端
  5. 浏览器再次访问 baidu 站点时,浏览器会将保存在本地的用户 ID 发给 baidu 服务端

服务端收到浏览器发送的用户 ID 后,就知道此次请求来自于一个已经登陆的用户。在以上的交互过程中,保存在客户端的用户 ID 就被称为 Cookie。

通过设置 HTTP 的 Set-Cookie 消息头,Web 服务器将 Cookie 发送给浏览器。Set-Cookie 消息的格式如下面所示,括号中的部分都是可选的:

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

消息头的第一部分,value 部分,通常是一个 name=value 格式的字符串。

服务端向客户端发送的 HTTP 响应中设置 HTTP 的 Set-Cookie 消息头,一个具体的例子如下:

Connection:keep-alive
Content-Type:text/plain
Date:Fri, 14 Jul 2017 10:49:23 GMT
Set-Cookie:user=ZhangSan
Transfer-Encoding:chunked

在这个例子中,服务端向客户端发送的 HTTP 消息头中,设置了 ‘Set-Cookie:user=ZhangSan’,客户端浏览器将接受到字符串 ‘user=ZhangSan’ 作为 Cookie,下次访问网站时,浏览器会将该 Cookie 发送给服务端。

客户端收到服务端的 Cookie 后,该 Cookie 会在接下来的每个请求中被发送至服务器。Cookie 的值被存储在名为 Cookie 的 HTTP 消息头中,并且只包含了 Cookie 的值,其它的选项全部被去除。

客户端向服务端发送的 HTTP 请求中设置 Cookie 消息头,一个具体的例子如下:

Connection:keep-alive
Cookie:user=ZhangSan
Host:localhost:8080
User-Agent:Mozilla/5.0 AppleWebKit/537.36 Chrome Safari

在这个例子中,客户端向服务端发送的 HTTP 消息头中,设置了 ‘Cookie:user=ZhangSan’,服务端接受到字符串 ‘user=ZhangSan’ 作为 Cookie,从而确认此次请求对应的用户。

4. Session 简介

Session 是在服务端保存的一个数据结构,用来存储用户的信息 (例如登录状态、用户名称),Session 数据可以保存在内存、文件或者数据库中。Session 有一个唯一标识 SID (Session ID),对应一个用户,在服务端使用 SID 可以查找到对应用户的数据。

假设有 2 个用户:用户 A 和用户 B;在服务端存在 2 个 Session,用于存储用户 A 和用户 B 的数据,如下图所示:

图片描述

在服务端使用 SID 查找 Session 的过程如下:

  • 每一个 Session 有一个唯一标识 SID,用户 A 的 Sesion 的 SID 为 0,用户 B 的 Sesion 的 SID 为 1;
  • 用户访问网站时,会把自己的 SID 作为 Cookie 发送给服务端
  • 服务端则根据请求中的 SID 来寻找对应的 Session。

通过一个具体的例子,解释如何使用 Cookie 实现 Session。使用 Cookie 实现 Session 包含有两个步骤:

1. 首次访问,服务端发送 Set-Cookie 消息头

图片描述

首先,客户端首次访问网站时,服务端创建一个 Session 用于记录用户的信息,使用一个唯一的会话 ID 标识该 Session。

然后,服务端将会话 ID 通过 Set-Cookie 消息头 (例如,Set-Cookie: sid=0) 发给客户端,客户端保存这个会话 ID。

在上图中,存在两个用户:用户 A 和用户 B,服务端为它们分别创建一个 Session。每个 Session 拥有一个唯一的 SID,用户 A 的 SID 等于 0,用户 B 的 SID 等于 1。

2. 后续访问,客户端发送 Cookie 消息头

图片描述

客户再次访问服务端时,会将会话 ID 通过 Cookie 消息头发给服务端,服务端根据请求中的 SID,寻找相应的 Session,该 Session 中存储相应用的数据。最后,服务端将特定用户的数据发给客户端。

6. 小结

本小节讲解了 Session 和 Cookie 的概念,使用思维导图概括如下:

图片描述

在下一个小节中,通过实例讲解如何在 Flask 中使用 Cookie 和 Session。