Node.js JWT

308 阅读2分钟

JWT 的使用场景

  • 身份验证:用户登录后,服务器生成一个 JWT 并返回给客户端。客户端在后续请求中发送该 JWT,服务器通过解析 JWT 确认用户身份。
  • 信息传递:JWT 可以携带自定义信息,并通过数字签名保证其安全性,适合在不同服务之间传递数据。

JWT 的结构

一个典型的 JWT 长这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImpvaG5kb2UiLCJpYXQiOjE1MTYyMzkwMjJ9.sflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
  • 头部 (Header):指定加密算法,通常是 HMAC SHA256 或 RSA。
  • 载荷 (Payload):包含用户信息和声明 (claims),如用户名、用户 ID、过期时间等。
  • 签名 (Signature):通过头部和载荷进行加密,用于确保数据没有被篡改。

在 Node.js 中使用 JWT

使用 jsonwebtoken 库可以方便地在 Node.js 中生成和验证 JWT。

1. 安装 jsonwebtoken

npm install jsonwebtoken

2. 生成 JWT:

const jwt = require('jsonwebtoken');

// 创建一个 JWT,传入用户信息并设置密钥
const token = jwt.sign({ username: 'johndoe' }, 'your-secret-key', { expiresIn: '1h' });

console.log(token); // 打印生成的 token
  • sign 方法的参数包括:用户信息(载荷)、密钥、以及可选的过期时间等配置。

3. 验证 JWT:

const jwt = require('jsonwebtoken');

// 验证客户端传递过来的 JWT
const token = 'eyJhbGciOiJIUzI1NiIsInR...'; // 客户端传来的 JWT

jwt.verify(token, 'your-secret-key', (err, decoded) => {
  if (err) {
    console.error('Token 验证失败:', err);
  } else {
    console.log('Token 验证成功,用户信息:', decoded);
  }
});
  • verify 方法接受三个参数:JWT、密钥、回调函数。通过回调函数可以获取验证后的解码信息或错误。

4. 设置过期时间:

JWT 支持设置过期时间,常用的方式是通过 expiresIn 参数指定过期时间。

// 生成一个过期时间为 1 小时的 token
const token = jwt.sign({ username: 'johndoe' }, 'your-secret-key', { expiresIn: '1h' });

使用场景示例:用户登录验证

以下是一个简单的登录示例,用户成功登录后生成并返回 JWT,后续请求中使用该 JWT 验证身份。

const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();

app.use(express.json());

const users = [
  { id: 1, username: 'johndoe', password: 'password123' }
];

// 登录接口
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  const user = users.find(u => u.username === username && u.password === password);

  if (user) {
    // 用户验证通过,生成 JWT
    const token = jwt.sign({ id: user.id, username: user.username }, 'your-secret-key', { expiresIn: '1h' });
    res.json({ token });
  } else {
    res.status(401).send('用户名或密码错误');
  }
});

// 受保护的路由
app.get('/protected', (req, res) => {
  const token = req.headers.authorization;

  if (!token) {
    return res.status(403).send('Token 缺失');
  }

  // 验证 token
  jwt.verify(token, 'your-secret-key', (err, decoded) => {
    if (err) {
      return res.status(401).send('无效的 token');
    } else {
      res.json({ message: '成功访问受保护的路由', user: decoded });
    }
  });
});

app.listen(3000, () => {
  console.log('服务器启动,监听端口 3000');
});

常见问题:

  1. JWT 如何保存?

    • 前端通常将 JWT 保存在 localStoragesessionStorage 中,也可以放在 HTTP Cookie 中。
  2. JWT 的安全性?

    • 确保使用强加密算法,如 HS256RS256
    • 避免将敏感信息(如密码)存放在 JWT 中。
    • 使用 HTTPS 传输 JWT,防止中间人攻击。
  3. JWT 的续签机制?

    • 使用刷新令牌(refresh token)机制,可以在 JWT 过期后为用户重新生成一个新的 JWT。