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

React+Express应用Facebook登录后后端数据未更新问题求助

问题描述

我开发了一个React前端+Express后端的RESTful API Web应用,支持邮箱/密码和Facebook两种登录方式。目前遇到的问题是:

  • Facebook登录时,用户的邮箱、姓名等初始数据可以正常存入数据库;
  • 但后续尝试更新用户数据时,数据无法传递到后端完成更新;
  • 使用Postman测试后端更新接口时,功能完全正常。

已尝试以下方案但未解决:

  • 使用PUT方法发起更新请求
  • 传递固定测试数据
  • 为Facebook用户创建独立数据库表

使用Passport.js实现Facebook登录,核心代码片段如下:

passport.use(
  new FacebookStrategy(
    {
      clientID: 'CLIENT_ID',
      clientSecret: 'CLIENT_SECRET',
      callbackURL: 'http://localhost:5003/facebook/callback',
      profileFields: ['id', 'displayName', 'name', 'gender', 'picture.type(large)', 'email'],
    },
    async function (token, refreshToken, profile, done) {
      try {
        let user = await FacebookUser.findOne({ where: { id: profile.id } });

        if (user) {
          console.log('User found!', user.id);
          return done(null, user);
        } else {
          const newUser = await FacebookUser.create({
            id: profile.id,
            name: profile.name.familyName,
            email: profile.emails[0].value,
            picture: profile.photos[0].value,
          });

          await fbCoins.create({
            facebookId: newUser.id,
            coins: 100,
          });

          console.log('User and Coins entry created successfully');
          return done(null, newUser);
        }
      } catch (err) {
        console.error('Error during Facebook authentication:', err);
        return done(err);
      }
    }
  )
);

app.get('/auth/facebook', passport.authenticate('facebook', { scope: 'email' }));

app.get(
  '/facebook/callback',
  passport.authenticate('facebook', {
    failureRedirect: '/failed',
  }),
  function (req, res) {
    var userId = req.user.dataValues.id;
    res.redirect('http://localhost:5173/home?fb_user_id=' + userId);
  }
);

app.get('/home', isLoggedIn, (req, res) => {
  console.log(req.user.id);
  res.render('profile', { user: req.user });
});

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

passport.serializeUser(function (user, done) {
  done(null, user.id);
});

passport.deserializeUser(function (id, done) {
  FacebookUser.findByPk(id, function (err, user) {
    return done(err, user);
  });
});
可能的原因及解决方案

1. 跨域请求未携带会话凭证

React前端(端口5173)和Express后端(端口5003)属于跨域环境,前端发起更新请求时如果没有携带会话凭证,后端的session cookie不会被传递,导致isLoggedIn中间件无法识别已登录用户,请求被拦截。

解决步骤:

  • 后端配置CORS允许凭证:
    安装并配置cors中间件,开启credentials:
    const cors = require('cors');
    app.use(cors({
      origin: 'http://localhost:5173', // 前端地址
      credentials: true // 允许携带会话凭证
    }));
    
  • 前端请求时携带凭证:
    使用axios或fetch发起请求时,开启凭证携带:
    // Axios示例
    axios.put('/api/update-user', updateData, {
      withCredentials: true
    });
    
    // Fetch示例
    fetch('http://localhost:5003/api/update-user', {
      method: 'PUT',
      credentials: 'include',
      body: JSON.stringify(updateData),
      headers: { 'Content-Type': 'application/json' }
    });
    

2. 更新接口未正确验证用户身份

如果更新接口没有使用isLoggedIn中间件,或依赖前端传递的fb_user_id而非req.user获取用户ID,会导致身份验证失效或用户ID被篡改。

解决步骤:

  • 给更新接口添加isLoggedIn中间件,从req.user获取当前登录用户ID:
    app.put('/api/update-user', isLoggedIn, async (req, res) => {
      try {
        const { id } = req.user; // 从会话中获取用户ID,避免前端传递参数
        const updateData = req.body;
        await FacebookUser.update(updateData, { where: { id } });
        res.status(200).json({ message: '更新成功' });
      } catch (err) {
        res.status(500).json({ error: err.message });
      }
    });
    

3. Passport反序列化函数异步逻辑异常

deserializeUser使用回调式findByPk,与代码中其他async/await风格不一致,可能导致用户信息无法正确反序列化,req.user获取失败。

解决步骤:

将deserializeUser改为异步函数,保持代码风格统一:

passport.deserializeUser(async function (id, done) {
  try {
    const user = await FacebookUser.findByPk(id);
    done(null, user);
  } catch (err) {
    done(err, null);
  }
});

4. 前端会话同步不完整

Facebook登录后,后端通过重定向传递fb_user_id到前端,但前端未主动验证会话状态,导致后续请求无法关联到后端session。

解决步骤:

  • 前端在/home页面加载时,发起验证请求确认会话:
    // React组件示例
    useEffect(() => {
      const checkAuth = async () => {
        const response = await fetch('http://localhost:5003/api/check-auth', {
          credentials: 'include'
        });
        const user = await response.json();
        // 将用户信息存入状态管理
      };
      checkAuth();
    }, []);
    
  • 后端添加会话验证接口:
    app.get('/api/check-auth', isLoggedIn, (req, res) => {
      res.json({ user: req.user });
    });
    
验证流程
  1. 配置CORS并开启凭证后重启后端;
  2. 前端更新请求携带credentials;
  3. 确认更新接口使用isLoggedIn中间件并从req.user取用户ID;
  4. 测试Facebook登录后的更新功能,查看后端日志确认req.user是否正确获取。

内容的提问来源于stack exchange,提问作者Madusha Bandara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 20:05:55