Passport.deserializeUser函数未触发问题排查求助
Passport反序列化函数未调用问题排查
我尝试了多种方法,但Passport的反序列化功能始终无法正常工作。用户通过Google账号登录时,若数据库中无匹配googleId的用户,会创建临时会话,这部分序列化流程正常,但后续请求中deserializeUser从未被调用,导致req.user为undefined,无法验证用户身份完成后续注册步骤。
相关代码片段
passport.js配置
const passport = require('passport'); const GoogleStrategy = require('passport-google-oauth20').Strategy; const User = require('../models/User'); module.exports = function(passport) { passport.use(new GoogleStrategy({ clientID: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, callbackURL: 'https://messenger-tu85.onrender.com/auth/google/callback', }, (accessToken, refreshToken, profile, done) => { User.findOne({ googleId: profile.id }) .then(existingUser => { if (existingUser) { console.log('Existing user found:', existingUser); return done(null, existingUser); } else { const tempUser = { googleId: profile.id, email: profile.emails[0].value }; console.log('Creating new temp user:', tempUser); return done(null, tempUser); } }) .catch(err => { console.error('Error finding user:', err); return done(err); }); } )); passport.serializeUser((user, done) => { console.log('Serialize user:', user); if (user._id) { done(null, user._id); } else { done(null, user.googleId); } }); passport.deserializeUser(async (id, done) => { try { // If id is an object and contains googleId, it’s a temporary user if (typeof id === 'object' && id.googleId) { done(null, id); } else { // If id is an _id, fetch the user from the database const user = await User.findById(id); done(null, user); } } catch (err) { done(err); } }); };
序列化流程正常,控制台输出:
Creating new temp user: { googleId: 'my google id', email: 'my gmail' } Serialize user: { googleId: 'my google id', email: 'my gmail' }
authRoutes.js配置
const express = require('express'); const passport = require('passport'); const router = express.Router(); router.get('/auth/google', passport.authenticate('google', { scope: ['profile', 'email'] })); router.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: 'https://svelte-of1p.onrender.com/signin' }), (req, res) => { if (req.user) { // Manually set the cookie res.cookie('connect.sid', req.sessionID, { maxAge: 24 * 60 * 60 * 1000, // 1 day secure: process.env.NODE_ENV === 'production', // True in production httpOnly: false, // Allow client-side access sameSite: 'None' // Allow cross-site cookies }); if (req.user.username) { res.redirect('https://svelte-of1p.onrender.com'); } else { res.redirect('https://svelte-of1p.onrender.com/select'); } } else { res.redirect('https://svelte-of1p.onrender.com/signin'); } } ); module.exports = router;
前端select/+page.svelte代码
const checkUserStatus = async () => { try { console.log('checkUserStatus function called'); const response = await fetch('https://messenger-tu85.onrender.com/api/check-new-user', { credentials: 'include' }); console.log('Response status:', response.status); if (response.status === 401) { console.log('Unauthorized: Redirecting to sign-in page'); window.location.href = '/signin'; return; } const data = await response.json(); console.log('Response data:', data); userExists = data.exists; if (userExists) { console.log('User exists: Redirecting to messages'); window.location.href = '/messages'; } else { console.log('User does not exist: Enabling form'); errorMessage = ''; successMessage = ''; formDisabled = false; } } catch (error) { console.error('Error checking user status:', error); } }; onMount(checkUserStatus);
后端checkNewUser中间件
const User = require('../models/User'); const checkNewUser = async (req, res, next) => { try { console.log('checkNewUser middleware called'); console.log('Request received:', { headers: req.headers, body: req.body, user: req.user }); // Correctly check for req.user.googleId directly if (!req.user || !req.user.googleId) { console.log('Unauthorized: No user or user ID found'); return res.status(401).json({ error: 'Unauthorized' }); } const googleId = req.user.googleId; console.log('Checking existing user with Google ID:', googleId); const existingUser = await User.findOne({ googleId }); if (existingUser) { console.log('Existing user found:', existingUser); if (existingUser.username) { console.log('User has a username'); return res.json({ exists: true }); } else { console.log('User does not have a username'); return res.json({ exists: false }); } } else { console.log('No existing user found'); return res.json({ exists: false }); } } catch (error) { console.error('Error checking user:', error); res.status(500).json({ error: 'Server error' }); } }; module.exports = checkNewUser;
控制台输出显示user: undefined,说明deserializeUser未被调用。
server.js中间件配置(关键部分)
const express = require('express'); const WebSocket = require('ws'); const app = express(); const port = 3000; const { createServer } = require('http'); const dotenv = require('dotenv'); const passport = require('passport'); const selectUser = require('./controllers/selectUser'); const checkNewUser = require('./middleware/checkNewUser'); const cors = require('cors'); const session = require('express-session'); const MongoStore = require('connect-mongo'); dotenv.config(); const connectDB = require('./config/mongoose'); connectDB(); // Use CORS middleware before any other middleware app.use(cors({ origin: 'https://svelte-of1p.onrender.com', credentials: true })); // Use session middleware before Passport initialization app.use(session({ secret: process.env.SECRET, resave: false, saveUninitialized: false, store: MongoStore.create({ mongoUrl: process.env.MONGODB_URI, collectionName: 'sessions' }), cookie: { maxAge: 24 * 60 * 60 * 1000, // 1 day httpOnly: false, sameSite: 'none' } })); // Initialize Passport after session middleware const initializePassport = require('./config/passport'); initializePassport(passport); app.use(express.urlencoded({ extended: true })); app.use(express.json()); app.use(passport.initialize()); app.use(passport.session()); app.use('/', require('./controllers/authControllers/authRoutes')); app.use('/', require('./controllers/authControllers/usernameRoutes')); app.use('/api/users', require('./controllers/users')); app.use('/api/messages', require('./controllers/messageController')); app.use('/api/select-user', selectUser.selectUser); app.use('/api/selected-users', require('./controllers/selectedUsers')); app.use('/api/check-new-user', checkNewUser);
已尝试方案
- 使用cookie-session、cookie-parser
- 移除cookie的secure属性
- 强制调用
req.login() - 确认中间件顺序正确
- 自定义反序列化中间件(从请求头提取cookie、会话ID查询用户,可运行但处理临时/注册用户时存在问题)
希望使用Passport自带的deserializeUser功能,请问为何该函数未被调用?
内容的提问来源于stack exchange,提问作者hypedstan
相关产品推荐
相关产品推荐

