Node.js JWT 认证实战:Express + Passport 的登录鉴权与权限控制

详解 Node.js 后端 JWT 认证的完整实现:Token 签发与验证、Refresh Token 机制、Password 中间件、Role-Based 权限控制、Rate Limiting 防暴力破解。含 Express 完整代码。

JWT(JSON Web Token)是现代 Web 应用的标准认证方案:无状态、自包含、可跨域。本文详解 Node.js 后端 JWT 认证的完整实现。


一、JWT 基础

JWT 由三部分组成:Header.Payload.Signature

Header: 算法类型(HS256/RS256)
Payload: 声明(用户ID、角色、过期时间)
Signature: 签名防篡改

双 Token 策略

Token有效期用途
Access Token15 分钟API 请求鉴权
Refresh Token7-30 天刷新 Access Token

二、Express 实现

npm install jsonwebtoken bcryptjs express-rate-limit
npm install -D @types/jsonwebtoken @types/bcryptjs
// auth.ts
import jwt from 'jsonwebtoken';
import bcrypt from 'bcryptjs';

const ACCESS_SECRET = process.env.JWT_ACCESS_SECRET!;
const REFRESH_SECRET = process.env.JWT_REFRESH_SECRET!;

export async function hashPassword(password: string): Promise<string> {
  return bcrypt.hash(password, 12);
}

export async function verifyPassword(password: string, hash: string): Promise<boolean> {
  return bcrypt.compare(password, hash);
}

export function generateTokens(userId: string, role: string) {
  const accessToken = jwt.sign({ sub: userId, role }, ACCESS_SECRET, { expiresIn: '15m' });
  const refreshToken = jwt.sign({ sub: userId }, REFRESH_SECRET, { expiresIn: '7d' });
  return { accessToken, refreshToken };
}

// 验证中间件
export function authenticate(req: Request, res: Response, next: NextFunction) {
  const token = req.headers.authorization?.replace('Bearer ', '');
  if (!token) return res.status(401).json({ error: 'Unauthorized' });

  try {
    const payload = jwt.verify(token, ACCESS_SECRET) as { sub: string; role: string };
    req.user = payload;
    next();
  } catch {
    res.status(401).json({ error: 'Invalid token' });
  }
}

三、Rate Limiting 防暴力破解

import rateLimit from 'express-rate-limit';

const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 分钟
  max: 5, // 最多 5 次尝试
  message: { error: 'Too many login attempts' },
});

app.post('/login', loginLimiter, async (req, res) => {
  // 登录逻辑
});

四、Role-Based 权限

export function authorize(roles: string[]) {
  return (req: Request, res: Response, next: NextFunction) => {
    if (!req.user || !roles.includes(req.user.role)) {
      return res.status(403).json({ error: 'Forbidden' });
    }
    next();
  };
}

// 使用
app.delete('/users/:id', authenticate, authorize(['admin']), deleteUser);

相关阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「frontend」更多文章