文章目录

Node.js 认证:JWT 与 Passport.js

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

Node.js 认证:JWT 与 Passport.js

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

  1. 打开 终端并 进入 目标工作目录。
  2. 执行 npm init -y 生成 基础项目配置文件。
  3. 运行 npm install express jsonwebtoken passport passport-jwt bcryptjs 下载 必需模块。express 负责搭建 HTTP 服务,jsonwebtoken 处理令牌签发与解析,passportpassport-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)

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

扫一扫,手机查看

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