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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 14:07:04