抽离Passport.js的isAuthorized模块后req.isAuthenticated报错解决方案
问题根源
你之前的操作犯了一个核心错误:把原本负责初始化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
相关产品推荐
相关产品推荐

