cookie 是什么
HTTP(Hypertext Transfer protocol,超文本传输协议) 有一个很重要的特点:
无状态性:这也就是说每个请求都是独立的,服务器不会记住之前的请求状态
。随着互联网的发展,交互式 Web
兴起,而 HTTP
无状态的特点严重影响其发展。
交互式
Web
:客户端与服务器可以交互,比如用户登陆,购物,论坛等
网景公司(Netscape) 当时一名员工 Lou Montulli(卢-蒙特利)
,在1994年将 cookies
的概念应用于网络通信,用来解决用户网上购物的购物车历史记录
问题。到目前为止,所有浏览器都支持 Cookie
。
这里的 cookie
,指的就是 HTTP Cookie
(也叫做 Web Cookie
或者浏览器 Cookie
)。Cookie
是服务端发送到用户浏览器并保存在浏览器本地
的一小块数据。
浏览器会存储 Cookie
并在下一次向同一个服务器再发起请求时携带并发送到服务器上。 Cookie
通过用户的浏览器在服务器和浏览器之间传递。
Cookie
通常包含了一些键值对,用于标识用户和存储相关的信息。
Cookie
的作用是在用户访问同一网站或者相关网站时,用于认证用户、追踪用户行为,存储用户偏好设置等。网站可以通过读取和写入 Cookie
来实现个性化的用户体验,如记住用户的登录状态、购物车内容、语言偏好等等。
cookie 的工作流程
上面已经提及了 HTTP
是无状态的。我们在浏览平常的新闻的时候,无需认证,但是,我们在新闻下评论,那就需要认证了。上图给出了简单的 cookie
运行机制的介绍。简单归总如下:
- 浏览器发起一个
HTTP
请求,比如用户账号/密码登陆 - 服务器端,对用户账号密码进行验证,验证用户通过后,将用户的信息封装成
cookie
,比如:ctx.cookies.set('userId', '123456')
。然后把设置的cookie
信息通过HTTP
响应返回给浏览器 - 浏览器接收到返回的
cookie
信息,并将其保存在内存或者硬盘中。然后之后的每次HTTP
请求都会带上用户的cookie
信息,比如userId=123456
- 服务端获取到
cookie
信息,解析了cookie
,获取到用户的信息,这里指userId=123456
,然后返回相关的用户信息
一般来说,具有过期时间的
cookie
存储在硬盘中,方便浏览器关闭后仍然保存;而会话cookie
存储在内存中,随着浏览器关闭而被删除。
演示
下面,我们来演示如何设置 cookie
。
案例的演示环境:
macOS Monterey
- Apple M1
node version
- v14.18.1
Visual Studio Code
及其Live Server
插件
我们已经了解了 cookie
的工作流程,下面会分同源和跨源来展示案例。
首先,我们添加个 hostname
, 方便测试,当然你可以直接使用 ip
地址测试。
通过 sudo vim /etc/hosts
添加 127.0.0.1 a.example.com
的映射:
同源案例
这里我们使用了 Koa
框架开发服务端,为了方便管理路由,我们引入 koa-router
库,代码如下:
javascript
复制代码
// index.js const Koa = require('koa'); const app = new Koa(); const Router = require('koa-router'); const router = new Router(); // 模拟登陆 router.get('/api/same_origin_request', async (ctx, next) => { ctx.cookies.set('username', 'same-origin-jimmy'); ctx.response.body = { message: 'Hello! Jimmy.' } }); // 模拟登陆后的请求 router.get('/api/same_origin_another_request', async (ctx, next) => { ctx.response.body = { message: 'Hello! Ivy.' } }); app.use(router.routes()); app.listen(3000, () => { console.log("Server is running on port 3000"); })
上面,我们编写了两个路由,路由 /api/same_origin_request
模拟我们登陆,假设验证了用户/密码,然后设定 username
的 cookie
信息,并返回信息;路由 /api/same_origin_another_request
模拟登陆后,获取指定用户的资源信息(验证是否带上了 cookie 信息发送到服务端)