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

如何解决Node.js中TypeError: req.isAuthenticated is not a function错误?

问题

使用Node.js、Express、EJS、Passport.js、express-session搭建网站,配置了/admin相关路由,但访问/admin路径或相关路由时出现错误:TypeError: req.isAuthenticated is not a function。

相关代码如下:

app.js

const express = require('express')
const ejsLayouts = require('express-ejs-layouts');
const cors = require('cors');
const webRoutes = require('./routes/webRoutes')
const userRoutes = require('./routes/userRoutes')

const app = express()

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/public'));
app.use(cors());

app.set('view engine', 'ejs');
app.use(ejsLayouts);

// Middleware to set currentPage variable
app.use(function(req, res, next) {
    res.locals.currentPage = req.path;
    next();
});

app.use("/", webRoutes);
app.use("/admin", userRoutes);

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log('listening on port 3000');
});

passport-config.js

const LocalStrategy = require('passport-local').Strategy
const bcrypt = require('bcrypt')

function initialize(passport, getUserByEmail, getUserById) {
  const authenticateUser = async (email, password, done) => {
    const user = getUserByEmail(email)
    if (user == null) {
      return done(null, false, { message: 'No user with that email' })
    }

    try {
      if (await bcrypt.compare(password, user.password)) {
        return done(null, user)
      } else {
        return done(null, false, { message: 'Password incorrect' })
      }
    } catch (e) {
      return done(e)
    }
  }

  passport.use(new LocalStrategy({ usernameField: 'email' }, authenticateUser))
  passport.serializeUser((user, done) => done(null, user.id))
  passport.deserializeUser((id, done) => {
    return done(null, getUserById(id))
  })
}

module.exports = initialize

userRoutes.js

if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config()
}

const express = require('express');
const app = express();
const router = express.Router();
const bcrypt = require('bcrypt');
const passport = require('passport');
const flash = require('express-flash');
const session = require('express-session');
const methodOverride = require('method-override');

const initializePassport = require('../passport-config')
initializePassport(
    passport, 
    email => users.find(user => user.email === email),
    id => users.find(user => user.id === id)
)

const users = []

 app.use(flash())
app.use(session({
    secret: process.env.SECRET_KEY,
    resave: false,
    saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.use(methodOverride('_method'))

// Middleware to set layout for all admin routes
router.use((req, res, next) => {
    res.locals.layout = 'layout_admin'; // Specify the admin layout
    next();
});

router.get('/', checkAuthenticated, (req, res) => {
    res.render('./admin/admin_home', {name: req.body.name});
});

router.get('/login', checkNotAutenticated, (req, res) => {
    res.render('./admin/admin_login');
});

router.post('/login', checkNotAutenticated, passport.authenticate('local', {
    successRedirect: '/',
    failureRedirect: 'login',
    failureFlash: true
}) )

router.get('/register', checkNotAutenticated, (req, res) => {
    res.render('./admin/admin_register');
});

router.post('/register', checkNotAutenticated, async (req, res) => {

    try {
        const hashedPass = await bcrypt.hash(req.body.password, 10)
        users.push({
            id: Date.now().toString(),
            name: req.body.name,
            email: req.body.email,
            password: hashedPass
        })

        res.redirect('login')
    } catch (err) {
        res.redirect('register')
    }
    console.log(users)
});

router.delete('/logout', (req, res) => {
    req.logOut()
    res.redirect('login')
})

function checkAuthenticated(req, res, next) {
    if (req.isAuthenticated()) {
        return next()
    }

    res.redirect('login')
}

function checkNotAutenticated(req, res, next) {
    if (req.isAuthenticated()) {
        return res.redirect('/')
    }
    next()

}

module.exports = router;
解决方法

出现req.isAuthenticated is not a function的核心原因是:Passport和express-session的中间件没有挂载到主Express应用上,而是错误地挂载到了userRoutes.js里新建的局部app实例上,导致/admin路由无法访问到这些中间件提供的方法。

步骤1:将Passport、Session等中间件移到主app.js中

在app.js中引入并配置flash、session、passport相关中间件,确保它们在挂载路由之前执行。修改后的app.js代码如下:

const express = require('express')
const ejsLayouts = require('express-ejs-layouts');
const cors = require('cors');
const flash = require('express-flash');
const session = require('express-session');
const passport = require('passport');
const methodOverride = require('method-override');
const webRoutes = require('./routes/webRoutes')
const userRoutes = require('./routes/userRoutes')

const app = express()

// 基础中间件
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/public'));
app.use(cors());

// 视图引擎配置
app.set('view engine', 'ejs');
app.use(ejsLayouts);

// 认证相关中间件(必须挂载在路由之前)
app.use(flash())
app.use(session({
    secret: process.env.SECRET_KEY,
    resave: false,
    saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.use(methodOverride('_method'))

// 初始化Passport
const initializePassport = require('./passport-config')
// 实际项目建议用数据库存储用户,此处为示例临时定义
const users = []
initializePassport(
    passport, 
    email => users.find(user => user.email === email),
    id => users.find(user => user.id === id)
)

// Middleware to set currentPage variable
app.use(function(req, res, next) {
    res.locals.currentPage = req.path;
    next();
});

// 挂载路由
app.use("/", webRoutes);
app.use("/admin", userRoutes);

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log('listening on port 3000');
});

步骤2:修改userRoutes.js,移除局部app实例和重复配置

删除userRoutes.js中新建的app实例,以及flash、session、passport相关的中间件挂载代码,使用主app中初始化好的passport实例。修改后的userRoutes.js代码如下:

if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config()
}

const express = require('express');
const router = express.Router();
const bcrypt = require('bcrypt');
const passport = require('passport');

// 注意:需和app.js中的users数组保持一致,实际项目用数据库
const users = []

// Middleware to set layout for all admin routes
router.use((req, res, next) => {
    res.locals.layout = 'layout_admin'; // Specify the admin layout
    next();
});

router.get('/', checkAuthenticated, (req, res) => {
    // 登录后用户信息存储在req.user中,而非req.body
    res.render('./admin/admin_home', {name: req.user.name});
});

router.get('/login', checkNotAutenticated, (req, res) => {
    res.render('./admin/admin_login');
});

router.post('/login', checkNotAutenticated, passport.authenticate('local', {
    successRedirect: '/admin', // 修正跳转路径到admin首页
    failureRedirect: '/admin/login',
    failureFlash: true
}) )

router.get('/register', checkNotAutenticated, (req, res) => {
    res.render('./admin/admin_register');
});

router.post('/register', checkNotAutenticated, async (req, res) => {
    try {
        const hashedPass = await bcrypt.hash(req.body.password, 10)
        users.push({
            id: Date.now().toString(),
            name: req.body.name,
            email: req.body.email,
            password: hashedPass
        })
        res.redirect('/admin/login')
    } catch (err) {
        res.redirect('/admin/register')
    }
    console.log(users)
});

router.delete('/logout', (req, res) => {
    // 新版本Passport的logOut需要回调处理错误
    req.logOut(function(err) {
        if (err) { return next(err); }
        res.redirect('/admin/login')
    })
})

function checkAuthenticated(req, res, next) {
    if (req.isAuthenticated()) {
        return next()
    }
    res.redirect('/admin/login')
}

function checkNotAutenticated(req, res, next) {
    if (req.isAuthenticated()) {
        return res.redirect('/admin')
    }
    next()
}

module.exports = router;

额外注意点

  1. 用户信息获取:登录成功后,用户信息存储在req.user中,而非req.body.name,需修正渲染数据来源。
  2. 路径跳转修正:确保所有/admin相关的跳转路径是完整路径,避免跳转到根路径或错误页面。
  3. req.logOut的回调:新版本Passport的req.logOut必须传入回调函数处理可能的错误。
  4. 用户数据存储:示例中用内存数组存储用户仅作演示,实际项目需使用数据库(如MongoDB、MySQL)持久化存储。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 14:15:56