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

使用Passport.js时报错req.isAuthenticated is not a function如何解决?

问题原因
  • 中间件挂载实例错误,未生效
    你在路由文件内部新建了独立的app实例,将session、passport相关的中间件全部挂载到了这个内部的app上,但你最终导出的是router,项目入口文件引入该路由时,使用的是入口的app实例,这个实例从未加载过passport相关中间件,因此req对象上不会被挂载isAuthenticated方法。
  • passport-config.js存在多处语法/逻辑错误
    1. LocalStrategy的验证函数参数错误:你写的authenticateUser只接收了done参数,函数内部直接使用的req未被传入,无法获取请求参数
    2. serializeUser和deserializeUser的参数错误,且访问了不存在的变量:两个方法的第一个参数分别是用户对象、用户id,你都未声明,同时代码中引用的userFound是authenticateUser内部的局部变量,外部无法访问,会直接报错
修复方案

1. 调整项目结构,修正中间件挂载逻辑

把路由文件里的app实例创建、中间件挂载逻辑全部删除,移到项目入口文件(比如app.js/index.js)中,入口文件参考结构:

const express = require('express')
const passport = require('passport')
const flash = require('express-flash')
const session = require('express-session')
const methodOverride = require('method-override')
const userRouter = require('./routes/users.route') // 引入你的路由文件
const initializePassport = require('./passport-config')
initializePassport(passport)

const app = express()
// 挂载全局中间件,顺序不能乱
app.use(express.json()) // 解析json格式请求体
app.use(express.urlencoded({ extended: false })) // 解析表单格式请求体
app.use(flash())
app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.use(methodOverride('_method'))

// 挂载路由
app.use(userRouter)

app.listen(3000, () => console.log('服务启动成功'))

路由文件中仅保留路由定义、校验中间件定义即可。

2. 修正passport-config.js代码

const User = require('./models/user.model')
const LocalStrategy = require('passport-local').Strategy
const bcrypt = require('bcrypt')

function initializePassport(passport) {
    // 开启passReqToCallback才能在验证函数中拿到req对象
    passport.use(new LocalStrategy( 
      { usernameField: 'email', passReqToCallback: true }, 
      async (req, email, password, done) => {
        try {
          /* 校验对应邮箱的用户是否存在 */
          const userFound = await User.findOne({email: email})
          if (!userFound) return done(null, false, {message: 'Cannot find user with that email'})
          
          /* 校验密码是否正确 */
          const checkPassword = await bcrypt.compare(password, userFound.password)
          if (checkPassword) {
              return done(null, userFound)
          } else {
              return done(null, false, {message: 'Incorrect password'})
          }
        } catch (err) {
          return done(err)
        }
    }))

    // 修正序列化参数
    passport.serializeUser((user, done) => { done(null, user.id) })
    // 修正反序列化逻辑,根据存储的id查询用户
    passport.deserializeUser(async (id, done) => { 
      const user = await User.findById(id)
      done(null, user) 
    })
}

module.exports = initializePassport
额外优化建议
  • 注册接口的user.save()是异步方法,建议加上await,避免逻辑时序问题
  • 新版Passport中req.logOut()是异步方法,需要传入回调函数处理异常,参考写法:
router.delete('/logout', (req, res, next) => {
  req.logOut((err) => {
    if (err) return next(err)
    res.redirect('/login')
  })
})

内容的提问来源于stack exchange,提问作者German Cocca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 22:45:04