JWT

json_web_token2026-10-16 14:45:19

JWT(JSON Web Token)是一种用于在各方之间安全地传输信息的紧凑且自包含的令牌。它通常用于身份验证和信息交换。JWT 由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。

JWT 的结构

一个 JWT 令牌通常由三个部分组成,每部分之间用点(.)分隔:

header.payload.signature

1. 头部(Header)

头部通常包含两部分:令牌类型(即 JWT)和所使用的签名算法(如 HMAC SHA256 或 RSA)。

示例:

{
  "alg": "HS256",
  "typ": "JWT"
}

然后将头部进行 Base64Url 编码,得到 JWT 的第一部分。

2. 载荷(Payload)

载荷部分包含声明(claims),声明是关于实体(通常是用户)和其他数据的声明。声明有三种类型:注册声明、公共声明和私有声明。

示例:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

然后将载荷进行 Base64Url 编码,得到 JWT 的第二部分。

3. 签名(Signature)

签名部分是为了确保令牌在传输过程中不被篡改。首先将头部和载荷进行 Base64Url 编码,然后使用指定的签名算法和一个密钥对它们进行签名。

示例(使用 HMAC SHA256 算法):

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

完整的 JWT 示例

假设我们有以下头部和载荷:

头部:

{
  "alg": "HS256",
  "typ": "JWT"
}

载荷:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

使用密钥 your-256-bit-secret 进行签名,生成的 JWT 可能如下所示:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

JWT 的使用场景

  1. 身份验证:JWT 最常见的使用场景是身份验证。服务器在用户登录时生成一个 JWT,并将其返回给客户端。客户端在后续请求中将 JWT 附加到请求头中,服务器通过验证 JWT 来确认用户身份。
  2. 信息交换:JWT 可以安全地传输信息,因为它们可以被签名。例如,使用公钥/私钥对 JWT 进行签名,接收方可以验证 JWT 的真实性。

示例:使用 Node.js 和 Express 生成和验证 JWT

以下是一个简单的示例,展示如何使用 Node.js 和 Express 生成和验证 JWT:

const express = require('express');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');

const app = express();
const PORT = 3000;
const SECRET_KEY = 'your_secret_key';

app.use(bodyParser.json());

// Mock user data
const users = {
  user1: 'password1',
  user2: 'password2'
};

// Login route
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  if (users[username] && users[username] === password) {
    const token = jwt.sign({ username }, SECRET_KEY, { expiresIn: '1h' });
    res.json({ token });
  } else {
    res.status(401).send('Invalid credentials');
  }
});

// Protected route
app.get('/protected', (req, res) => {
  const token = req.headers['authorization'];
  if (!token) {
    return res.status(403).send('Token is required');
  }
  try {
    const decoded = jwt.verify(token, SECRET_KEY);
    res.json({ message: 'This is a protected resource', user: decoded.username });
  } catch (err) {
    res.status(401).send('Invalid token');
  }
});

app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

这个示例展示了如何生成和验证 JWT。用户通过 /login 路由进行认证,成功后获得一个 JWT。访问受保护资源时,用户需要在请求头中包含该 JWT,服务器验证令牌后授予访问权限。

验证与失效的边界

前文的三段式结构是常见 JWS 紧凑表示,不能据此概括所有 JWT 形式;加密 JWT 还涉及 JWE。Base64URL 编码不是加密,签名 JWT 的载荷通常可被持有者读取,因此不应放入不应泄露的秘密。

验证时应显式约束允许的算法,并按协议校验签发者、受众、有效期及令牌用途,不能仅凭解码成功或签名通过就授予任意资源权限。

自包含令牌不会因为前端删除副本就自动撤销。短有效期、服务端撤销记录或其他会话机制各有代价,应按实际退出与权限更新要求选择。

前面的 Express 代码用于说明流程;硬编码密钥、明文示例密码和直接读取整个 authorization 头不能作为完整生产认证方案。实际方案还需安全存储凭据、按所用认证方案解析请求头,并与资源级授权配合。

参考:JWT 安全最佳实践 RFC 8725。

本页目录