Skip to content

JWT (JSON Web Token) 验证接口

以下是标准的 JWT (JSON Web Token) 验证接口 的实现示例,包括 生成 Token验证 Token刷新 Token 的核心逻辑,适用于大多数 Web 框架(如 Express.js、Spring Boot、Django 等)。


1. JWT 验证接口设计

接口功能

  • 生成 Token:用户登录后签发 JWT
  • 验证 Token:保护需要认证的接口
  • 刷新 Token:当 Token 快过期时刷新

依赖库

  • 推荐使用 jsonwebtoken(Node.js)、jjwt(Java)、PyJWT(Python)
  • 需要密钥(SECRET_KEY)和过期时间配置

2. 代码实现示例(Node.js + Express)

(1) 生成 Token

javascript
const jwt = require('jsonwebtoken');
const SECRET_KEY = 'your-secret-key'; // 实际项目中应使用环境变量存储
const EXPIRES_IN = '1h'; // Token 有效期

// 登录接口:生成 Token
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  
  // 1. 验证用户名密码(模拟)
  if (username !== 'admin' || password !== '123456') {
    return res.status(401).json({ error: 'Invalid credentials' });
  }

  // 2. 生成 JWT
  const payload = { userId: 1, username: username };
  const token = jwt.sign(payload, SECRET_KEY, { expiresIn: EXPIRES_IN });

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

(2) 验证 Token(中间件)

javascript
// JWT 验证中间件
function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1]; // Bearer <token>

  if (!token) return res.status(401).json({ error: 'Missing token' });

  jwt.verify(token, SECRET_KEY, (err, user) => {
    if (err) return res.status(403).json({ error: 'Invalid or expired token' });
    req.user = user; // 将解码后的用户信息附加到请求对象
    next();
  });
}

// 受保护的路由
app.get('/protected', authenticateToken, (req, res) => {
  res.json({ message: `Hello, ${req.user.username}!` });
});

(3) 刷新 Token

javascript
app.post('/refresh-token', (req, res) => {
  const { token } = req.body;
  if (!token) return res.status(401).json({ error: 'Token required' });

  jwt.verify(token, SECRET_KEY, (err, user) => {
    if (err) return res.status(403).json({ error: 'Invalid token' });

    // 检查 Token 是否快过期(例如剩余时间 < 15分钟)
    const decoded = jwt.decode(token);
    const now = Math.floor(Date.now() / 1000);
    if (decoded.exp - now > 900) { // 15分钟 = 900秒
      return res.status(400).json({ error: 'Token not expired yet' });
    }

    // 生成新 Token(移除旧 Token 的过期时间)
    const newToken = jwt.sign({ userId: user.userId, username: user.username }, SECRET_KEY, { expiresIn: EXPIRES_IN });
    res.json({ token: newToken });
  });
});

3. 关键安全注意事项

  1. 密钥管理

    • 永远不要将 SECRET_KEY 硬编码在代码中,使用环境变量(如 process.env.JWT_SECRET)。
    • 定期轮换密钥(如每 3 个月)。
  2. Token 存储

    • 客户端:建议存于 HttpOnly Cookie 或 localStorage(需防范 XSS)。
    • 服务端:可结合 Redis 实现 Token 黑名单(用于注销)。
  3. 防止 CSRF

    • 如果使用 Cookie,需配合 CSRF Token。
  4. 过期时间

    • 访问令牌(Access Token):建议短(如 15分钟~1小时)
    • 刷新令牌(Refresh Token):可较长(如 7天),但需安全存储

4. 其他语言示例

Java (Spring Boot)

java
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

// 生成 Token
String token = Jwts.builder()
    .setSubject(username)
    .setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1小时
    .signWith(SignatureAlgorithm.HS512, SECRET_KEY)
    .compact();

// 验证 Token
Claims claims = Jwts.parser()
    .setSigningKey(SECRET_KEY)
    .parseClaimsJws(token)
    .getBody();

Python (Django/Flask)

python
import jwt

# 生成 Token
token = jwt.encode({'user_id': 1, 'exp': datetime.utcnow() + timedelta(hours=1)}, SECRET_KEY, algorithm='HS256')

# 验证 Token
try:
    payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
except jwt.ExpiredSignatureError:
    return {"error": "Token expired"}

5. 测试工具(Postman)

  1. 登录接口POST /login → 获取 Token
  2. 访问受保护接口:在 Headers 中添加:
    Authorization: Bearer <your-token>

如果需要针对特定框架或场景的详细实现,请告知您的技术栈(如 Spring Security、Django REST Framework 等)。

Released under the MIT License.