使用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
相关产品推荐
相关产品推荐

