JWT的构成

JWT即JSON Web Token,由三部分组成:头部(Header)、载荷(Payload)和签名(Signature),它们用 . 分隔,形如eyhhhhhhh.eyppppp.ssssss

Header:包含令牌的类型(JWT)和签名算法

Payload:包含声明(用户id、角色等)和一些元数据(比如过期时间)

Signature:通过HeaderPayload结合一个密钥(secret)生成的签名,用于验证令牌的完整性和真实性

JWT的鉴权流程

用户登陆时输入账号密码 => 服务端验证后生成JWT返回给客户端 => 客户端将JWT储存到本地(或cookie)中,在后续请求时将其加入到请求头(如Authorization: Bearer token)=> 服务器在每次用户请求时验证JWT的有效性,如果有效则允许正常访问受保护的资源

常见用法

比如nodejs中jsonwebtoken

//npm install jsonwebtoken
import jwt from 'jsonwebtoken'
jwt.sign(payload, secretOrPrivateKey, [options, callback])

参数说明

  1. payload:要加密到 token 里的数据内容(负载)String|buffer|object
  2. secretOrPrivateKey:用于签名的密钥(对称加密)或私钥(非对称加密)String|buffer|object
  3. options:设置 token 的一些选项,比如过期时间、算法等。是一个对象如{ expiresIn: '1h', algorithm: 'HS256' }
  4. callback:是一个函数,如果使用回调函数sign会变成异步,回调参数为(err, token)
//同步用法
const token = jwt.sign({ userId: 123 }, 'mySecret', { expiresIn: '1h' });
//异步用法
jwt.sign({ userId: 123 }, 'mySecret', { expiresIn: '1h' }, function(err, token) {
  // 处理 token 或错误
});

payload, secretOrPrivateKey是必须的参数。

简单例子

import express from 'express';
import jwt from 'jsonwebtoken'

const app = express();
app.use(express.json());

// 模拟用户数据库
const users = [
  { id: 1, username: 'admin', password: '123456' }
];

// JWT 密钥(生产环境中应使用环境变量存储)
const SECRET_KEY = 'my-secret-key';

// 登录路由 - 生成 JWT
app.post('/login', (req, res) => {
  const { username, password } = req.body;

  // 查找用户
  const user = users.find(u => u.username === username && u.password === password);
  if (!user) {
    return res.status(401).json({ message: 'Invalid credentials' });
  }

  // 生成 JWT
  const token = jwt.sign(
    { userId: user.id, username: user.username }, // Payload
    SECRET_KEY, // 密钥
    { expiresIn: '1h' } // 令牌过期时间
  );

  res.json({ token });
});

// 中间件 - 验证 JWT
const authenticateToken = (req, res, next) => {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1]; // 提取 Bearer 后面的 token

  if (!token) {
    return res.status(401).json({ message: 'Authentication token missing' });
  }

  try {
    // 验证 token
    const decoded = jwt.verify(token, SECRET_KEY);
    req.user = decoded; // 将解码后的用户信息附加到请求对象
    next(); // 继续处理请求
  } catch (error) {
    return res.status(403).json({ message: 'Invalid or expired token' });
  }
};

// 受保护的路由 - 需要 JWT 验证 
app.get('/protected', authenticateToken, (req, res) => {
  res.json({ message: 'Protected data', user: req.user });
});

// 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});
  1. 使用post方式在请求体中添加内容获取token

    http://localhost:3000/login

    {
      "username": "admin",
      "password": "123456"
    }
  2. 将token添加到Header后使用get方法访问保护目录进行验证http://localhost:3000/protected
{
  "message": "Protected data",
  "user": {
    "userId": 1,
    "username": "admin",
    "iat": 1747386742,
    "exp": 1747390342
  }
}
最后修改:2025 年 05 月 16 日
如果觉得我的文章对你有用,请随意赞赏