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

使用Passport.js登录后,React组件通过Axios获取用户信息遇req.user为空求助

问题分析与解决方案

1. 修复登录API的核心问题

你的登录接口只是创建了User实例,并没有去数据库验证该用户是否存在、密码是否正确,直接调用req.login会导致Passport无法正确识别合法用户,后续req.user自然为空。同时代码里还有变量错误(response应该是res)。

修正后的登录API示例(假设你用Mongoose+Passport Local策略):

app.post("/login", async function (req, res) {
  try {
    // 先从数据库查询用户
    const user = await User.findOne({ username: req.body.email });
    if (!user) {
      return res.status(400).send({ message: "用户不存在" });
    }

    // 验证密码(假设密码用bcrypt加密存储)
    const isPasswordValid = await bcrypt.compare(req.body.password, user.password);
    if (!isPasswordValid) {
      return res.status(400).send({ message: "密码错误" });
    }

    // 验证通过后调用req.login
    req.login(user, function (err) {
      if (err) {
        console.log(err);
        return res.status(400).send({ message: "登录失败" });
      }
      res.redirect("http://localhost:3000");
    });
  } catch (err) {
    console.log(err);
    res.status(500).send({ message: "服务器错误" });
  }
});

2. 配置Passport序列化/反序列化逻辑

Passport需要明确如何将用户信息存入Session、如何从Session中还原用户,必须添加以下配置:

// 序列化用户:将用户ID存入Session
passport.serializeUser(function(user, done) {
  done(null, user.id);
});

// 反序列化用户:通过Session中的ID查询数据库获取完整用户信息
passport.deserializeUser(async function(id, done) {
  try {
    const user = await User.findById(id);
    done(null, user);
  } catch (err) {
    done(err, null);
  }
});

3. 正确加载Express Session与Passport中间件

确保中间件加载顺序正确,Session必须在Passport之前:

const session = require('express-session');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;

// 配置Session
app.use(session({
  secret: '自定义加密密钥',
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: false, // 开发环境设为false,生产环境HTTPS下改为true
    maxAge: 24 * 60 * 60 * 1000 // Session有效期1天
  }
}));

// 初始化Passport
app.use(passport.initialize());
app.use(passport.session()); // 必须在express-session之后

// 配置Passport Local策略
passport.use(new LocalStrategy(
  function(username, password, done) {
    User.findOne({ username: username }, function (err, user) {
      if (err) { return done(err); }
      if (!user) { return done(null, false, { message: '用户不存在' }); }
      // 密码验证逻辑
      bcrypt.compare(password, user.password, function(err, isValid) {
        if (err) { return done(err); }
        if (!isValid) { return done(null, false, { message: '密码错误' }); }
        return done(null, user);
      });
    });
  }
));

4. 配置跨域(CORS)支持

因为前后端跨域,需要在Express中允许携带凭证:

const cors = require('cors');

app.use(cors({
  origin: 'http://localhost:3000', // 允许的前端域名
  credentials: true // 允许携带Cookie/Session凭证
}));

5. 完善/keeper接口

添加未认证时的响应逻辑:

app.get("/keeper", (req, res) => {
  if(req.isAuthenticated()) {
    res.status(200).send({
      success: true,
      message: "success",
      user: req.user
    });
  } else {
    res.status(401).send({
      success: false,
      message: "用户未登录"
    });
  }
});

6. 调整React Keeper组件的请求逻辑

在Axios请求成功后,将用户信息存入状态:

useEffect(() => {
  const getUser = () => {
    const configuration = {
      method: "get",
      url: "http://localhost:5000/keeper",
      withCredentials: true
    };

    axios(configuration)
    .then((result) => {
      console.log(result);
      setUser(result.data.user); // 存入用户信息
    })
    .catch((error) => {
      console.log(error);
      // 可添加未登录时的跳转逻辑
    });
  };
  getUser();
}, []);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 19:40:29