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

抽离Passport.js的isAuthorized模块后req.isAuthenticated报错解决方案

解决Passport.js抽离isAuthorized中间件后req.isAuthenticated is not a function的问题

问题根源

你之前的操作犯了一个核心错误:把原本负责初始化Passport和Session的模块,直接替换成了只导出isAuthorized函数。这导致Passport的核心中间件(passport.initialize()、passport.session())以及Session配置完全没有被执行,req对象上自然不会挂载isAuthenticated方法,也就出现了那个错误。

正确实现方案

我们需要保留Passport的初始化逻辑,同时把isAuthorized作为模块的一部分导出,而不是替换整个模块的导出内容。

1. 修改passport.js文件

保持原有初始化逻辑不变,新增isAuthorized函数并单独导出:

const axios = require('axios')
const uuid = require('uuid/v4')
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const session = require('express-session')
const mongoStore = require('connect-mongo')(session)

// 定义鉴权中间件
function isAuthorized(req, res, next) {
  if (req.isAuthenticated()) {
    console.log('Is allowed')
    next()
  } else {
    console.log('Is not allowed')
    res.sendStatus(401) // 可根据需求改成 res.redirect('/')
  }
}

// 保留原有的Passport初始化逻辑
module.exports = (app) => {
  const users = [
    { id: '2f24vvg', email: 'test@test.com', password: 'password' }
  ]
  const mongoSessionStore = new mongoStore({
    url: 'mongodb://localhost/test-app',
    ttl: 30 * 60 // 30分钟
  })
  let sess = {
    genid: (req) => {
      console.log('Inside the session middleware')
      console.log(req.sessionID)
      return uuid()
    },
    store: mongoSessionStore,
    secret: 'keyboard cat', // 生产环境建议从环境变量读取,比如process.env.SESSION_SECRET
    resave: false,
    rolling: true,
    saveUninitialized: true,
    unset: 'destroy',
    cookie: {
      HttpOnly: true,
      maxAge: 30 * 60 * 1000 // 30分钟
    }
  }
  app.use(session(sess))
  passport.use(new LocalStrategy(
    { usernameField: 'email' },
    (email, password, done) => {
      axios.get(`http://localhost:5000/users?email=${email}`)
        .then(res => {
          const user = res.data[0]
          if (!user) {
            return done(null, false, { message: 'Invalid credentials.\n' })
          }
          // 注意:生产环境绝对不能明文对比密码,要用bcrypt等哈希算法!
          if (password != user.password) {
            return done(null, false, { message: 'Invalid password.\n' })
          }
          return done(null, user)
        })
        .catch(error => done(error))
    }
  ))
  passport.serializeUser((user, done) => {
    console.log('Inside serializeUser callback. User id is saved to the session store')
    done(null, user.id)
  })
  passport.deserializeUser((id, done) => {
    axios.get(`http://localhost:5000/users/${id}`)
      .then(res => done(null, res.data))
      .catch(error => done(error, false))
  })
  app.use(passport.initialize())
  app.use(passport.session())
}

// 单独导出鉴权中间件
module.exports.isAuthorized = isAuthorized

2. 在路由文件中正确使用

首先确保你的Express主文件(比如app.js)已经加载了Passport初始化模块:

// app.js中
const express = require('express')
const app = express()
// 加载Passport配置
require('./passport')(app)

然后在路由文件中引入并使用isAuthorized:

const express = require('express')
const router = express.Router()
// 解构引入鉴权中间件
const { isAuthorized } = require('../passport')

// 示例使用
router.get('/secure', isAuthorized, (req, res) => {
  res.format({
    html: () => {
      res.render('secure')
    },
    json: () => {
      res.send({ message: 'you reached the secure endpoint' })
    }
  })
})

module.exports = router

额外注意事项

  • 生产环境不要明文存储/对比密码,一定要用bcrypt或argon2这类哈希算法处理密码。
  • Session的secret建议从环境变量读取,避免硬编码泄露风险。
  • 确保Passport初始化逻辑在所有路由之前执行,否则中间件不会生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 17:43:15