# 使用 Cookie 和 Session

URL: https://caijiao.org/express/chapter8/1-cookie-session
Source: docs/express/chapter8/1-cookie-session.md
Description: 本章节介绍如何在 Express 应用中使用 Cookie 和 Session 来管理用户状态，实现用户身份验证和会话跟踪。

在 Web 应用中，Cookie 和 Session 是用于管理用户会话和持久化数据的常见方式。它们能够在客户端和服务器之间保持状态，尤其在用户身份验证、购物车、用户偏好等场景中非常有用。本章节将介绍如何在 Express 中使用 Cookie 和 Session。

## 什么是 Cookie？

Cookie 是一种存储在客户端浏览器中的小型数据文件，它能够在不同的请求之间保持状态。每次用户发送请求时，浏览器会自动将与该网站相关的 Cookie 发送到服务器。Cookie 常用于存储用户的登录状态、用户偏好设置等信息。

### 设置 Cookie

可以通过 `res.cookie()` 方法在响应中设置 Cookie。以下是一个简单的设置 Cookie 的例子：

```js
app.get('/set-cookie', (req, res) => {
  res.cookie('username', 'john_doe');  // 设置一个名为 'username' 的 Cookie
  res.send('Cookie 已设置');
});
````

在上述例子中，`res.cookie()` 设置了一个名为 `username` 的 Cookie，值为 `john_doe`。这个 Cookie 将会存储在客户端的浏览器中。

### 读取 Cookie

在 Express 中，我们可以通过 `req.cookies` 访问客户端发送的 Cookie。要读取 Cookie，首先需要使用 `cookie-parser` 中间件来解析 Cookie。

```bash
npm install cookie-parser
```

```js
const cookieParser = require('cookie-parser');
app.use(cookieParser()); // 使用 cookie-parser 中间件解析 Cookie

app.get('/get-cookie', (req, res) => {
  const username = req.cookies.username;  // 获取 'username' Cookie 的值
  res.send(`Cookie 中的用户名是：${username}`);
});
```

### 删除 Cookie

可以通过 `res.clearCookie()` 方法删除 Cookie：

```js
app.get('/clear-cookie', (req, res) => {
  res.clearCookie('username');  // 删除 'username' Cookie
  res.send('Cookie 已删除');
});
```

## 什么是 Session？

Session 是一种在服务器端存储用户会话信息的技术。与 Cookie 不同，Session 数据存储在服务器端，而客户端仅保存一个用于标识会话的 ID（通常是通过 Cookie 来传递）。Session 使得服务器能够在多个请求之间维护用户的状态信息。

### 使用 Session

在 Express 中使用 Session，可以通过 `express-session` 中间件来管理。首先需要安装 `express-session`：

```bash
npm install express-session
```

然后，通过 `app.use()` 使用 `express-session` 中间件：

```js
const session = require('express-session');

app.use(session({
  secret: 'your-secret-key',  // 用于加密 Session ID 的密钥
  resave: false,              // 是否每次请求都重新保存 Session
  saveUninitialized: true,    // 是否保存未初始化的 Session
  cookie: { secure: false }   // 设置 cookie 的安全属性，开发环境中可以设置为 false
}));
```

在上述代码中，`express-session` 中间件将会自动生成一个会话 ID，并在客户端通过 Cookie 进行传递。会话数据将存储在服务器端。

### 设置 Session 数据

可以通过 `req.session` 对象来存储和访问 Session 数据：

```js
app.get('/set-session', (req, res) => {
  req.session.username = 'john_doe';  // 设置 Session 数据
  res.send('Session 已设置');
});
```

### 访问 Session 数据

通过 `req.session` 对象可以访问 Session 中存储的数据：

```js
app.get('/get-session', (req, res) => {
  const username = req.session.username;  // 访问 Session 数据
  res.send(`Session 中的用户名是：${username}`);
});
```

### 删除 Session 数据

可以通过 `req.session.destroy()` 删除整个 Session 数据：

```js
app.get('/destroy-session', (req, res) => {
  req.session.destroy((err) => {
    if (err) {
      return res.send('删除 Session 失败');
    }
    res.send('Session 已删除');
  });
});
```

## Cookie 与 Session 的区别

| 特性     | Cookie             | Session               |
| ------ | ------------------ | --------------------- |
| 存储位置   | 存储在客户端浏览器中         | 存储在服务器端               |
| 存储数据大小 | 数据存储在客户端，通常限制为 4KB | 数据存储在服务器端，无限制         |
| 安全性    | 安全性较低，容易被篡改        | 更加安全，数据存储在服务器中        |
| 生命周期   | 可以设置过期时间           | 会话结束时失效               |
| 性能     | 需要每次请求时发送给服务器      | 只有 Session ID 会发送给服务器 |

## 使用场景

### 1. **Cookie 使用场景**

* **用户登录状态**：存储用户的登录状态或用户 ID，使得用户在每次访问时都能保持登录状态。
* **用户偏好设置**：存储用户的主题、语言偏好等信息，提升用户体验。
* **追踪用户行为**：用于统计分析用户的行为，例如浏览记录等。

### 2. **Session 使用场景**

* **身份验证**：在用户登录后，使用 Session 保存用户的认证信息，避免每次请求都进行验证。
* **购物车**：在电商网站中，Session 可以用于保存购物车的数据，使得购物车信息跨请求持续有效。
* **会话跟踪**：用于保持多次请求之间的用户状态信息，确保用户体验一致。

## 总结

在本章节中，我们学习了如何在 Express 中使用 Cookie 和 Session 来管理用户状态：

* **Cookie**：存储在客户端，适用于保存轻量级的数据，如用户登录信息、用户偏好等。
* **Session**：存储在服务器端，适用于需要保存大量或敏感数据的情况，如用户身份验证和购物车信息。

通过合理使用 Cookie 和 Session，可以提高 Web 应用的用户体验并实现会话管理。在实际应用中，通常会结合使用 Cookie 和 Session 来提供更加稳定和安全的用户会话管理。
