You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js+Angular中Passport JWT返回Unauthorized问题求助

排查Passport JWT返回unauthorized错误的可能原因

问题背景

在Node.js(Sequelize+MySQL)和Angular项目中使用Passport JWT做身份验证,请求始终返回unauthorized错误,已尝试Stack Overflow方案但无效。相关代码如下:

Passport JWT配置代码

require('dotenv').config()
const user = require('../models/user');

const SECRET = process.env.REFRESH_TOKEN_SECRET;
const { Strategy, ExtractJwt } = require('passport-jwt');

const options = {
    jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
    secretOrKey: SECRET
}

module.exports = (passport) => {
    passport.use(new Strategy(options, async (payload, done) => {
        await user.findByPk(payload.userId).then(user => {
            if (user) {
                return done(null, user);
            }
            return done(null, false);
        }).catch(error => {
            return done(null, error);
        });
    }));
}

项目初始化配置(app.js)

app.use(passport.initialize());
require("./middleware/passport")(passport);

身份验证中间件(auth.js)

exports.userAuth = passport.authenticate("jwt", { session: false });

路由使用示例

router.get(
  '/categories',
  userAuth,
  checkRole(['admin', 'superadmin']),
  categoryController.getAllCategories
);

Angular拦截器代码

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // add authorization header with jwt token if available
    let currentUser = this.authenticationService.currentUserValue;
    if (currentUser && currentUser.token) {
      request = request.clone({
        setHeaders: {
          Authorization: `Bearer ${currentUser.token}`
        }
      });
    }

    return next.handle(request);
  }

可能的问题及排查步骤

1. JWT密钥不匹配

  • 检查生成JWT时使用的密钥和Passport配置中SECRET是否一致:当前代码用的是REFRESH_TOKEN_SECRET,确认生成访问令牌时是否用了同一个密钥。很多项目会区分访问令牌密钥和刷新令牌密钥,如果签令牌和验令牌用的密钥不一致,必然验证失败。
  • 直接打印process.env.REFRESH_TOKEN_SECRET,确认环境变量是否正确加载,有没有拼写错误(比如大小写、下划线)。

2. JWT Payload中的userId字段不匹配

  • 生成JWT时,确认存入的用户ID字段是userId还是其他(比如id)。如果生成时用的是payload: { id: user.id },但Passport里用payload.userId查询,自然找不到用户,返回false导致未授权。
  • 在Passport的验证回调里加日志,打印payload内容,确认userId是否存在且正确:
    passport.use(new Strategy(options, async (payload, done) => {
        console.log('JWT Payload:', payload); // 新增日志
        await user.findByPk(payload.userId).then(user => {
            // ...原有代码
        });
    }));
    

3. Sequelize查询用户时的问题

  • 确认user.findByPk(payload.userId)确实能查到用户:可以单独写个测试脚本,用已知存在的用户ID调用这个方法,看是否返回用户实例。
  • 注意Sequelize的findByPk默认会过滤软删除(带deletedAt字段)的用户,确认目标用户没有被软删除。
  • 回调里的错误处理逻辑有误:catch(error)里返回done(null, error),Passport会把错误对象当成用户返回,应该改成done(error, false),或者直接抛出错误。

4. 请求头中的Token格式问题

  • 检查Angular拦截器生成的Authorization头格式是否正确:必须是Bearer +空格+令牌,不能有多余空格或拼写错误(比如bearer小写)。
  • 在后端加日志,打印req.headers.authorization,确认Token是否正确传递到后端:
    app.use((req, res, next) => {
        console.log('Authorization Header:', req.headers.authorization);
        next();
    });
    
  • 确认后端CORS配置允许携带自定义头,避免请求头被拦截。

5. Token已过期或无效

  • 生成JWT时确认设置了合理的过期时间(比如expiresIn: '1h'),如果Token过期,Passport会直接返回未授权。
  • 解析前端发送的Token,确认签名是否有效、过期时间是否正常、Payload内容是否正确。

6. Passport初始化顺序问题

  • 确认app.use(passport.initialize())是在路由之前配置的,且require("./middleware/passport")(passport)正确执行了策略注册。如果路由先于Passport初始化,策略未注册会导致验证失败。

内容的提问来源于stack exchange,提问作者Prasad Gavande

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 23:28:15