Node.js 认证:JWT 与 Passport.js
阶段一:初始化项目与安装依赖
- 打开 终端并 进入 目标工作目录。
- 执行
npm init -y生成 基础项目配置文件。 - 运行
npm install express jsonwebtoken passport passport-jwt bcryptjs下载 必需模块。express负责搭建 HTTP 服务,jsonwebtoken处理令牌签发与解析,passport及passport-jwt提供标准化认证流程,bcryptjs用于安全加密用户密码。 - 创建
index.js作为 应用主入口。
阶段二:配置 Passport 与 JWT 策略
- 引入 核心依赖至文件顶部:
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(); - 定义 签名密钥参数。设置 一个强随机字符串,并通过环境变量实现生产环境隔离:
const JWT_SECRET = process.env.JWT_SECRET || 'dev_secret_key_replace_me'; const jwtOptions = { jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), secretOrKey: JWT_SECRET }; - 配置 验证回调函数。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); })); - 激活 全局中间件。在定义任何路由前 添加
app.use(express.json());启用 JSON 请求体解析,并 添加app.use(passport.initialize());注入 Passport 实例。
阶段三:编写登录与受保护路由
- 实现 登录凭证接口。接收客户端提交的账号密码,校验通过后 生成 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: '账号或密码错误' }); }); - 添加 权限拦截中间件。针对敏感业务接口 挂载
passport.authenticate('jwt', { session: false }),阻断未携带有效令牌的请求:app.get('/api/profile', passport.authenticate('jwt', { session: false }), (req, res) => { res.json({ message: '数据加载成功', data: req.user }); }); - 启动 HTTP 服务。在文件末尾 调用
app.listen(3000)并 输出 运行日志,准备接收外部请求。
阶段四:验证认证流程与排错
- 发起 身份验证请求。向
http://localhost:3000/api/login发送 POST 请求,请求体格式为{"username": "user", "password": "pass"}。 - 保存 响应中的
token字段。完整字符串以Bearer开头,后接由点号分隔的三段式数据。 - 携带 凭证访问受控接口。新增 请求头
Authorization,其值 粘贴 上一步获取的完整字符串,随后向http://localhost:3000/api/profile发送 GET 请求。 - 核对 服务端响应。若状态码为
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(长效),并 编写 专用的刷新端点拦截过期判断。
模块化重构结构
- 拆分
passport.js。移动 策略配置代码至独立文件,导出 初始化函数并在主文件中 调用。 - 隔离 路由逻辑。使用
express.Router()构建 路由实例,将登录与业务接口分别 挂载 至/api/auth与/api/users前缀。 - 集成 中间件管道。编写 统一的
requireAuth拦截器,替换 内联的passport.authenticate调用,统一 错误响应格式并 记录 访问日志。

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