Node.js(Express+Mongoose)Facebook登录回调异常:500错误无法跳转
Facebook登录回调500错误排查与修复
我正在开发一个基于Express+Mongoose的Node.js简易应用,采用Facebook登录作为用户认证方式。用户信息已能存储到MongoDB,但Facebook回调功能异常,登录成功后无法跳转到用户页面,出现500内部服务器错误。相关代码如下:
Passport.js代码
require('dotenv').config() const facebookStrategy = require('passport-facebook').Strategy const User = require('./model/user.mongo') module.exports = function(passport){ passport.use(new facebookStrategy({ clientID : process.env.client_id, clientSecret : process.env.client_secret, callbackURL : "http://localhost:8000/auth/facebook/callback" }, async function(token, refreshToken, profile, done) { try{ const user = await User.findOne({'username': profile.displayName}) if(user) { console.log('user found') //console.log(user) return done(null,user) } else { User.create({ username: profile.displayName }) return done(null,user) } } catch(err) { console.log(err) } console.log(profile) })) passport.serializeUser((user,done)=>{ done(user.id,null) }) passport.deserializeUser(async(id, done)=>{ try { const user = await User.findById(id) done(err, user); } catch(err) { console.log(err) } })}
auth.js代码
const express = require('express') const app = express() const authroute = express.Router() const passport = require('passport') authroute.get('/',(req,res)=>{ res.render('auth') }) authroute.get('/profile',isLoggedIn,(req,res)=>{ res.render('profile',{user:req.user}) }) function isLoggedIn(req,res,next) { if(req.isAuthenticated()) { return next() } return res.redirect('/auth') } authroute.get('/facebook',passport.authenticate('facebook',{ scope: [,'public_profile','email'] })) authroute.get('/facebook/callback',passport.authenticate('facebook', { failureRedirect: '/login', failureMessage: true }), function(req, res) { res.redirect('/user'); }) authroute.get('/logout',(req,res)=>{ req.logout() res.redirect('/auth') }) module.exports = {authroute}
index.js代码
const express = require('express') const app = express() app.use(express.json()) require('dotenv').config() const path = require('path') const http = require('http') const helmet = require('helmet') app.use(helmet()) const morgan = require('morgan') app.use(morgan('common')) const mongoose = require('mongoose') const server = http.createServer(app) const mongo_url = process.env.mongodb_url const bodyParser = require('body-parser') const {authroute} = require('./controller/auth') const {userroute} = require('./controller/user') const passport = require('passport') const session = require('express-session') const cookieParser = require('cookie-parser') app.use(bodyParser.urlencoded({extended: true})) app.set('views',path.join(__dirname,'views')) app.set('view engine','ejs') require('./passport')(passport) app.use(session({ secret: "Harvey_Specter", resave: false, saveUninitialized: true, })) app.use(passport.initialize()) app.use(passport.session()) app.use(cookieParser()) app.use('/auth',authroute) app.use('/user',userroute) server.listen(8000,async(req,res)=>{ await mongoose.connect(mongo_url,{ useNewUrlParser: true, useUnifiedTopology: true }).then(()=>{ console.log('mongodb connected') }).catch(err=>console.log(err)) console.log('server is connected') })
错误排查与修复方案
以下是代码中导致500错误的几个关键问题:
Passport序列化函数参数顺序错误
- 原代码:
passport.serializeUser((user,done)=>{ done(user.id,null) }) - 问题:
done函数参数顺序应为done(error, userIdentifier),这里颠倒了用户ID与错误参数的位置,导致Session存储异常。 - 修复:
passport.serializeUser((user,done)=>{ done(null, user.id) })
- 原代码:
反序列化函数未正确处理错误与结果
- 原代码:
passport.deserializeUser(async(id, done)=>{ try { const user = await User.findById(id) done(err, user); } catch(err) { console.log(err) } }) - 问题:
try块中err变量未定义,且捕获错误后未将错误传递给done函数,导致Passport无法处理异常。 - 修复:
passport.deserializeUser(async(id, done)=>{ try { const user = await User.findById(id) done(null, user); // 无错误时传递null和用户对象 } catch(err) { done(err, null); // 捕获错误时传递错误对象 } })
- 原代码:
创建用户时未等待异步操作完成
- 原代码:
else { User.create({ username: profile.displayName }) return done(null,user) } - 问题:
User.create是异步函数,未加await会导致user变量为undefined,Passport无法正确处理新用户。 - 修复:
else { const newUser = await User.create({ username: profile.displayName }) return done(null, newUser) }
- 原代码:
Facebook授权Scope数组格式错误
- 原代码:
scope: [,'public_profile','email'] - 问题:数组开头多余的逗号会导致无效的Scope参数,引发授权流程异常。
- 修复:
scope: ['public_profile','email']
- 原代码:
回调路由中无效的失败重定向地址
- 原代码:
{ failureRedirect: '/login', failureMessage: true } - 问题:应用中不存在
/login路由,失败时会触发404错误,进而导致500异常。 - 修复:改为已存在的
/auth路由:{ failureRedirect: '/auth', failureMessage: true }
- 原代码:
服务器监听回调参数错误
- 原代码:
server.listen(8000,async(req,res)=>{ - 问题:
server.listen的回调函数不需要req和res参数,无效参数可能引发不必要的错误。 - 修复:去掉多余参数:
server.listen(8000,async()=>{
- 原代码:
内容的提问来源于stack exchange,提问作者sathish
相关产品推荐
相关产品推荐

