cookie,英语意为“饼干,小点心”
session,英语意为“会议,会话”
一、起源
早期的网页,是科学家们为了传输、阅读科学技术方面的文档而诞生的,只能看一看简单的文字,连排版都没有。随着 CSS、JS 的发展,网页逐渐变得优美,变得可以互动,可以做一些人机交互。
随着宽带、服务器的不断发展,网页的进步取得了极大支持。当互联网走向民用、商业化后,网页应用中的各种问题随之而来。
http
虽然早期(1991年之前)网页的传输不是依靠 http,但 http 的诞生绝对是互联网历史以及 web 发展史上的重大事件。后来网页的数据传输都是依赖于 http 协议。这里就得讲一讲 http 的特点,因为这关系到 cookie 与 session 的诞生。
http 是一种无状态的传输协议。
在最初的设计上,它的主要目的是根据 URL (统一资源定位符)定位互联网上的主机及其资源。这种设计是比较简便的,定位资源位置、获取资源显得十分简单。
但随着民用、商业化的网页增多,一些需求和场景出现了:
某个网页,希望只有特殊人员可以访问,例如政府官员;某个商业网站,希望发展会员,需要记录会员的身份。某些网页更是需要对不同的用户进行不同使用权限的划分。
而 http 显然是做不到这点的,传输协议是一种中间态,它链接两个终端,负责二者之间的数据传输。它的初始设计也没法满足这种保存用户信息的需求:1991 年诞生的 http 协议 0.9 版本,是十分简单的请求设计,只有一行请求报文。
在1994 年,网景浏览器为了解决网络购物中的用户身份问题设计了 cookie,可以有效解决这一问题,许多浏览器也纷纷效仿,支持这一特性。
二、cookie 是什么?
cookie 是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息,用于服务器记录客户端的状态。
这里有两个重点:
- 服务器发给客户端
- 存放在客户端
假设现在是一个网站的登录页,用户点击登录后会发送相关的用户信息给服务器,服务器验证通过后会发送一个响应请求,在这个响应的响应头中会有一个Set-Cookie
:
HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie:
user_cookie=Rg3vHJZnehYLjVg7qi3bZjzg;
Expires=Tue, 18 Aug 2016 21:47:38 GMT;
Path=/aaa;
Domain=test.com;
HttpOnly
浏览器收到响应后发现有一个Set-Cookie
,就会把Set-Cookie
后的数据进行保存,在之后的每次的请求中就会把 cookie 也放在请求头中传给服务器,以此进行身份识别等功能。
这里我们可以看到,用户信息是保存在 cookie 中,也就相当于是保存在浏览器中,那就说用户可以随意修改用户信息,这是一种不安全的策略!
强调一点:cookie 无论是服务器发给浏览器还是浏览器发给服务器,都是放在请求头中的!
原理图示
cookie 的属性
从上面的代码中可以看到 cookie 的值有几个关键信息。首先明确一点,cookie 的文本是以“键值”形式存储的。从代码中也可以看到有user_cookie
,Expires
等键,每个键背后都有一个对应的值。
Name / Value
name 表示 cookie 的名称,服务器就是通过 name 属性来获取某个 cookie 值。
value 表示 cookie 的值,大多数情况下服务器会把这个 value 当作一个 key 去缓存中查询保存的数据。
Domain
domain 表示可以访问 cookie 的域名。
这里有一个访问规则:顶级域名只能设置或访问顶级域名的 cookie,二级及以下的域名只能访问或设置自身或者顶级域名的 cookie,所以如果要在多个二级域名中共享 cookie 的话,只能将 domain 属性设置为顶级域名!
Path
表示可以访问此 cookie 的页面路径。 比如 path=/test,那么只有 /test 路径下的页面可以读取此 cookie。
Expires / Max-Age
Expires / Max-Age 表示此 cookie 超时时间。若设置其值为一个时间,那么当到达此时间后,此 cookie 失效。当浏览器关闭(不是浏览器标签页,而是整个浏览器) 后,此 cookie 失效。
Size
表示 cookie 的 name+value 的字符数,比如又一个 cookie:id=666,那么 size=2+3=5。另外每个浏览器对 cookie 的支持都不相同,但都是 4kb 左右,上下一两个字节的差别。
httponly
若此属性为 true,则只有在 http 请求头中会带有此 cookie 的信息,而不能通过 document.cookie 来访问此 cookie。这是为了网站的安全,因为 cookie 保存的是用户信息,是十分敏感的安全问题,如果被攻击或者被窃取,将会影响巨大。
cookie 保存数量
- IE8+ 每个域名不超过 50 个 cookie
- Firefox 每个域名不超过 50 个 cookie
- Opera 每个域名不超过 30 cookie
- Safari 与 Chrome 似乎没有限制,但太多了服务器端也会有所限制。
session 是什么?
前面讲到,cookie 具有一定的安全隐患,因为用户信息是保存在浏览器端的,用户可以直接查看。既然 http 也无法处理用户状态,那只能将用户状态保存在服务器端才能避免这个问题了。
session 便是保存在服务器端的 cookie。
服务器为每个浏览器创建的一个会话对象,浏览器在第一次请求服务器,服务器便会为这个浏览器生成一个 session,并且把 sessionId 以 cookie 的形式发送给客户端浏览,而以用户显式结束或 session 超时为结束。
session 工作原理:
- 一个用户向服务器发送第一个请求时,服务器为其建立一个 session,并为此 session 创建一个标识号(sessionID)
- 这个用户随后的所有请求都应包括这个标识号。服务器会校对这个标识号以判断请求属于哪个 session
原理图示
后记
cookie 与 session 都是用于交互式 web 验证用户身份信息的手段,cookie 由服务器生成保存在客户端,缺点是不安全。session 由服务器生成,保存在服务器端,缺点是给服务器造成一定压力。
web 发展到今天已经出现了许多信息校验的手段,相对于 cookie 与 session 拥有安全、高效等优点。许多网站,例如 github 就提出弃用 cookie。但不论如何,这种方案在历史中解决了一个阶段的难题,许多老旧项目依旧在使用,也有许多应对 cookie 安全的方案。
历史不论如何前进,技术不论如何迭代,知其然知其所以然是一个良好的技术品质,应当一以贯之。