首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >HTTP Cookies与Session机制详解

HTTP Cookies与Session机制详解

原创
作者头像
写bug的高哈哈
发布2025-01-19 00:11:51
发布2025-01-19 00:11:51
3010
举报

HTTP 是一个“无状态协议”,也就是说,每次从客户端对服务器发出的请求都是独立的 — 这一次的请求无法得知上一次请求的内容与信息。

既然 HTTP 是一个无状态协议,那么服务器如何识别不同的请求是来自同一个浏览器?或者用户登录后,服务器如何在往后的请求中,识别用户其实已经通过验证(已登录)的状态? — 通过使用 Cookie 和 Session 可以解决这些问题。

Cookie

Cookie 是服务器传送给浏览器的一小段数据,并请浏览器保存起来,以便往后向相同的服务器发送请求时,附上这个 Cookie 的数据。

Cookie 常见用途

  1. 存储和跟踪用户行为
  2. 存储用户登录、购物车等服务器所需的信息
  3. 存储用户设置和偏好等

基本用户登录流程示例

  1. 用户通过浏览器登录界面登录
  2. 服务器端通过验证后,可以将用户“已经登录”的信息附在 Cookie 中回传,并请浏览器保存起来
  3. 往后,每当浏览器对服务器发出请求时,会一并附上存有用户“已经登录”状态信息的 Cookie 给服务器
  4. 服务器通过 Cookie 就能识别这位用户已经通过验证了

使用 Express 返回 Cookie

透過 res.setHeader(‘Set-Cookie’, <cookie-name>=<coolie-value>) 設定回傳 的 Cookie 和內容:

代码语言:javascript
复制
// 以登录例子做设置,在登录后附上含有“已登录状态”的 Cookie
app.post('/login', (req, res) => {
  res.setHeader('Set-Cookie', 'isLoggedIn=true')
  res.redirect('/')
})

在 DevTools Application 中查看返回的 Cookies

用戶请求都会携带 Cookie

代码语言:javascript
复制
app.get('/anotherPath', (req, res) => {
  const cookie = req.get('Cookie')
  console.log(cookie)
  res.render('anotherPage')
})

从下方 Terminal 的结果可以发现,不管是对 /anotherPath 这条路径,或其他相同服务器的不同路径发出请求,从该客户端向服务器发出的请求,都会附上包含 isLoggedIn 信息的 Cookie:

使用 Cookie 传送重要信息的安全隐患

通过 Cookie,我们的确达到目标,让服务器可以在往后通过客户端发出的请求,识别用户及其登录状态,非常方便。然而,有趣的是,这些信息其实用户是有机会可以在浏览器中修改的,因此用户能通过串改 Cookie 上的=内容,让服务器收到不正确的信息 — 也就是说,以登录的例子来看,用户可以在串改 isLoggedIn 的值,让服务器误以为用户已经通过认证:

尽量避免将敏感信息通过 Cookie 存在客户端

Session

我们了解到存放较敏感的信息在客户端是有安全上的疑虑,也因此我们改使用 Session 将用户相关的敏感信息存放在服务器端 — 可能在内存或数据库中 — 并创建一个相对应且独特的 ID(Session ID),在回传给客户端的 Cookie 中一并附上,未来客户端只要附上含有这个 Session ID 的 Cookie 给服务器,服务器就能匹配相对应的 Session — 也能找到需要的敏感数据了!

通过 MagicBand 了解 Cookie 和 Session 间的关系

想像你入住了迪士尼酒店,酒店告知有关你的入房、预约餐厅和游乐设施的信息都已经存在迪士尼的系统当中了,并附上一只专属的 MagicBand,手表芯片中有系统给你的专属 ID 号码,因此这几天在酒店直接感应房门、在餐厅或游乐设施前感应机器就能通过系统辨识完成开门和报到。

你的个人信息很重要,因此迪士尼将入房、预约信息以 Session 存放在系统中,这笔数据对应了一个独特的 Session ID。而 MagicBand 就像是 Cookie,当中带有这个 Session ID,当你透过 MagicBand 在感应机器时,系统就能快速辨识你的身份,并找到存放你入房和预约数据的 Session 了!

如同前面所说的,重要的信息不建议放在客户端 — 像是写在你的 MagicBand 上,你就有机会串改游乐设施的预约时间、其他人也有机会看到你的隐私等 — 若放在迪士尼的系统中(像是服务器的概念),就显得安全许多:你唯一需要的,是那只含有独特 ID 的 MagicBand 让系统辨识罢了!

在 Node.js 中使用 Session

  • 安裝 express-session 套件
代码语言:javascript
复制
$ npm install express-session
  • 引入 express-session 套件
代码语言:javascript
复制
// 引入 express-session 包
const session = require('express-session')
  • 创建 session 的 middleware
代码语言:javascript
复制
// 建立 session 的 middleware,并将在需要带入的属性放进 options 对象中
app.use(session(options))

options 对象中可以带入的属性非常多,其中最重要的是 secret — secret 的值将被用来做作为制造存放在 Cookie 当中的 hashed session ID,通常是一串很长的字符串:

补充:这边提到的 hashed session ID 可以想象是把你提供的 secret 字符串通过特殊的杂凑算法(hashing algorithm)生成的一组唯一 ID

代码语言:javascript
复制
// 例子
app.use(session({
  secret: 'sndkfnofnosfpowekmprwjqlierjw',
  // 代表在每次与用户互动后,不会强制把 session 存储,除非 session 有变动
  resave: false,
  saveUninitialized: false
}))
  • 存储和获取 session data
代码语言:javascript
复制
// 在 session 对象上新增 key 和 value
app.post('/login', (req, res) => {
  req.session.isLoggedIn = true
  res.redirect('/')
})

在浏览器发出登录请求后,可以看到多了一个 Cookie,其中的价值就是 hashed Session ID — 用来让服务器辨识和寻找相对应的 Session

为了验证同一个用户通过客户端发出的不同请求都会附上含有 Session ID 的 Cookie 给服务器,且服务器可以通过 Cookie 上的 Session ID 找到相对应的 Session data,我们在 / 路径的路由中,将 Session 中 isLoggedIn 的值打印出来看看:

代码语言:javascript
复制
// 在登录后,前往 / 路径
app.get('/', (req, res) => {
  // 将 session 对象打印出来
  console.log(req.session.isLoggedIn)
  res.redirect('index')
})

从上面登录案例的实验结果可以了解到:

  1. 用户敏感的信息(例如例子中“已登录状态”的信息)将被存放在服务器端,而不是客户端 — 因此客户无法任意在浏览器中修改,数据保存也较安全
  2. 服务器会将一个独特的 Session ID 附在回传的 Cookie 给浏览器 — 未来服务器只要通过这个 Session ID,就能找到相对应的 Session data(例如例子中用户提供了这个 Session ID,服务器就能知道该名用户已经登录过)
  3. 有了 Session ID 同一个用户通过客户端发出的“不同请求”给相同的服务器时,服务器都能识别对方为相同的浏览器(例如例子中,客户端在登录后,对 / 路径发出请求时,我们能看到 Session 当中 isLoggedIn 的值为 true )

结语

在没有使用 Cookie 和 Session 之前,照理来说,不同的请求都是独立的,这一次发出的请求是拿不到上一次的信息。然而通过 Session,我们得以将用户敏感信息存储在服务器端,搭配 Cookie,服务器得已通过客户端每次发出的不同请求,获取所需要的 Session ID ,找到需要使用的用户信息。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Cookie
    • Cookie 常见用途
    • 基本用户登录流程示例
    • 使用 Express 返回 Cookie
    • 在 DevTools Application 中查看返回的 Cookies
    • 用戶请求都会携带 Cookie
    • 使用 Cookie 传送重要信息的安全隐患
  • Session
    • 通过 MagicBand 了解 Cookie 和 Session 间的关系
    • 在 Node.js 中使用 Session
  • 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档