文章目录

Node.js 认证:JWT 与 Passport.js

发布于 2026-04-07 07:02:53 · 浏览 162 次 · 评论 0 条

Node.js 认证:JWT 与 Passport.js

阶段一:初始化项目与安装依赖

  1. 打开 终端并 进入 目标工作目录。
  2. 执行 npm init -y 生成 基础项目配置文件。
  3. 运行 npm install express jsonwebtoken passport passport-jwt bcryptjs 下载 必需模块。express 负责搭建 HTTP 服务,jsonwebtoken 处理令牌签发与解析,passport 及 passport-jwt 提供标准化认证流程,bcryptjs 用于安全加密用户密码。
  4. 创建 index.js 作为 应用主入口。

阶段二:配置 Passport 与 JWT 策略

  1. 引入 核心依赖至文件顶部:
    const express = require('express');
    const passport = require('passport');
    const JwtStrategy = require('passport-jwt').Strategy;
    const ExtractJwt = require('passport-jwt').ExtractJwt;
    const jwt = require('jsonwebtoken');
    const app = express();
  2. 定义 签名密钥参数。设置 一个强随机字符串,并通过环境变量实现生产环境隔离:
    const JWT_SECRET = process.env.JWT_SECRET || 'dev_secret_key_replace_me';
    const jwtOptions = {
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: JWT_SECRET
    };
  3. 配置 验证回调函数。Passport 在解码 JWT 成功后会调用此函数,用于确认用户是否依然有效。返回 done(null, user) 表示放行,返回 done(null, false) 表示拒绝:
    passport.use(new JwtStrategy(jwtOptions, (jwtPayload, done) => {
      // 此处应替换为实际数据库查询逻辑
      const user = { id: jwtPayload.sub, username: jwtPayload.username };
      if (user) {
        return done(null, user);
      }
      return done(null, false);
    }));
  4. 激活 全局中间件。在定义任何路由前 添加 app.use(express.json()); 启用 JSON 请求体解析,并 添加 app.use(passport.initialize()); 注入 Passport 实例。

阶段三:编写登录与受保护路由

  1. 实现 登录凭证接口。接收客户端提交的账号密码,校验通过后 生成 JWT 令牌:
    app.post('/api/login', (req, res) => {
      const { username, password } = req.body;
      // 实际场景需调用 bcrypt.compare 验证哈希密码
      if (username === 'user' && password === 'pass') {
        const payload = { sub: 1, username: 'user' };
        const token = jwt.sign(payload, JWT_SECRET, { expiresIn: '24h' });
        return res.json({ success: true, token: `Bearer ${token}` });
      }
      res.status(401).json({ success: false, message: '账号或密码错误' });
    });
  2. 添加 权限拦截中间件。针对敏感业务接口 挂载 passport.authenticate('jwt', { session: false }),阻断未携带有效令牌的请求:
    app.get('/api/profile', passport.authenticate('jwt', { session: false }), (req, res) => {
      res.json({ message: '数据加载成功', data: req.user });
    });
  3. 启动 HTTP 服务。在文件末尾 调用 app.listen(3000) 并 输出 运行日志,准备接收外部请求。

阶段四:验证认证流程与排错

  1. 发起 身份验证请求。向 http://localhost:3000/api/login 发送 POST 请求,请求体格式为 {"username": "user", "password": "pass"}。
  2. 保存 响应中的 token 字段。完整字符串以 Bearer 开头,后接由点号分隔的三段式数据。
  3. 携带 凭证访问受控接口。新增 请求头 Authorization,其值 粘贴 上一步获取的完整字符串,随后向 http://localhost:3000/api/profile 发送 GET 请求。
  4. 核对 服务端响应。若状态码为 200 且返回用户数据,确认 链路畅通。若触发 401,对照 下表快速定位问题:
错误提示 根本原因 修正操作
Unauthorized 请求头缺失 Authorization 或前缀拼写错误 检查 键名拼写,补充 Bearer 前缀(末尾必须含一个空格)
jwt malformed 令牌字符串包含多余引号、换行符或截断 清理 剪贴板残留字符,确保 仅传输纯文本令牌
strategy not loaded Passport 实例未正确挂载或中间件顺序颠倒 确认 app.use(passport.initialize()) 位于 所有路由注册之前

调整会话生命周期
在 jwt.sign 配置中 修改 expiresIn 数值。使用 30m 表示 30 分钟,使用 7d 表示 7 天。令牌失效后客户端 必须 重新执行 登录流程获取新凭证。如需实现无感续期,拆分 access_token(短效)与 refresh_token(长效),并 编写 专用的刷新端点拦截过期判断。

模块化重构结构

  1. 拆分 passport.js。移动 策略配置代码至独立文件,导出 初始化函数并在主文件中 调用。
  2. 隔离 路由逻辑。使用 express.Router() 构建 路由实例,将登录与业务接口分别 挂载 至 /api/auth 与 /api/users 前缀。
  3. 集成 中间件管道。编写 统一的 requireAuth 拦截器,替换 内联的 passport.authenticate 调用,统一 错误响应格式并 记录 访问日志。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文