Session 和 Cookie 的概念
网站通过 Session 和 Cookie 的机制记录访问者的一些基本信息,本小节依次讲解 Cookie 和 Session 的概念,并讲解了如何使用 Cookie 实现 Session。
1. 需求的提出
网站常常需要记录访问者的一些基本信息,例如:用户是否登录、用户登录名称、密码、用户在 Web 站点购物的方式或用户访问该站点的次数。
举个例子,用户在没有登陆 baidu 时,此时用户的身份是游客,baidu 首页的界面如下图所示:
当用户登陆 baidu 页面后,此时用户的身份是已登录用户,可以看到页面的右上角显示了用户的名称,如下图所示:
可以看出,baidu 服务端能够辨别用户的身份,根据用户是否登录显示不同的内容。如果用户的身份是游客,则显示文本登陆;如果用法的身份是已登录用户,则显示用户的名称。
2. 使用 Cookie 辨别用户身份
网站为了辨别用户身份、进行会话跟踪需要把一些数据 (例如:登录状态、用户名称) 储存在用户本地终端上,这些数据被称为 Cookie。
以登录 baidu 为例子,用户在没有登陆 baidu 时,访问的网页 URL 是 https://www.baidu.com;在登陆 baidu 后,访问的网页 URL 仍然是 https://www.baidu.com。访问的页面 URL 相同,但是这两次访问呈现的结果不相同,登陆前没有显示用户名,登陆后显示了用户名。
服务端是通过 Cookie 的技术区分这两次请求的,如下图所示:
- 用户登陆 baidu
- baidu 服务端会生成一个用户 ID
- baidu 服务端将这个用户 ID 发送给浏览器
- 浏览器收到这个用户 ID 后,会将这个用户 ID 保存在用户本地终端
- 浏览器再次访问 baidu 站点时,浏览器会将保存在本地的用户 ID 发给 baidu 服务端
服务端收到浏览器发送的用户 ID 后,就知道此次请求来自于一个已经登陆的用户。在以上的交互过程中,保存在客户端的用户 ID 就被称为 Cookie。
3. 发送 Cookie 的过程
3.1 在服务端发送 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 发送给服务端。
3.2 在客户端发送 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。
5. 使用 Cookie 实现 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。