NodeJS+Express-Session+Passport认证失败:AJAX请求无法通过认证
问题分析
你遇到的问题核心在于:手动访问接口时浏览器会自动携带session cookie,但AJAX请求默认不会主动发送这个凭证,再加上你的前后端属于跨域环境(前端80端口,后端8000端口),浏览器的同源策略会限制凭证的传递,最终导致后端无法识别已登录用户,req.user自然就成了undefined。
解决方案
1. 前端AJAX请求添加withCredentials: true
不管是POST还是GET类型的AJAX请求,都需要开启这个选项,告诉浏览器在跨域请求时主动携带session cookie。修改你的前端代码:
POST请求示例:
function registerWT() { console.log('registerWT started...') var rolle = 'wt'; var json = {"rolle": rolle}; $.ajax({ url: 'http://localhost:8000/user', type: 'POST', data: JSON.stringify(json), contentType: 'application/json; charset=utf-8', dataType: 'JSON', async: false, withCredentials: true, // 新增这一行 success: function (msg) { var js = JSON.stringify(msg); var state = msg['state']; if (state == true) { console.log('successfully created new user') } else { console.log('failed to create new user') } } }); }
GET请求示例:
function getTest() { console.log('YT'); $.ajax({ url: 'http://localhost:8000/user', type: 'GET', async: false, withCredentials: true, // 新增这一行 success: function (msg) { var state = msg['state']; if (state == true) { console.log('successfully created new user') } else { console.log('failed to create new user') } } }); }
2. 后端配置CORS允许凭证传递
因为前后端端口不同属于跨域场景,你需要在Express中配置CORS中间件,明确允许凭证传递,并且指定具体的前端origin(不能用*,否则浏览器会拒绝传递凭证)。
首先安装cors依赖:
npm install cors
然后在后端主文件中添加配置:
const cors = require('cors'); // 注意要放在app.use(session(...))之后 app.use(cors({ origin: 'http://localhost:80', // 你的前端实际地址 credentials: true, // 允许携带跨域凭证 }));
3. 调整Express Session的cookie配置
确保session的cookie设置符合浏览器的安全规则,避免被拒绝存储或发送:
app.use(session({ secret: "ahskfjdhkjshadkjfhlajsdhlfkj", resave: false, // 避免不必要的session重复存储 saveUninitialized: false, // 只在session有内容时才存储 cookie: { sameSite: 'lax', // 适配大多数场景,HTTPS环境可设为'none'(需配合secure: true) secure: false, // 本地HTTP环境设为false,线上HTTPS环境设为true httpOnly: true, // 开启防止XSS攻击,推荐配置 maxAge: 24 * 60 * 60 * 1000 // 可选:设置session有效期为1天 } }));
4. 完善Passport的序列化/反序列化逻辑
你提供的passportInit代码不完整,需要确保GoogleStrategy的回调能正确返回用户信息,并且序列化/反序列化逻辑能正常工作:
const GoogleStrategy = require('passport-google-oauth').OAuth2Strategy; const keys = require('../../config/keys') module.exports = (passport, db) => { // 注意传入db参数,方便反序列化时查询 passport.serializeUser((user, done) => { // 建议只序列化用户ID,减少session存储体积 done(null, user.profile.id); }); passport.deserializeUser((userId, done) => { // 从数据库查询完整用户信息,传递给后续请求 db.collection('users').findOne({userId: userId}, (err, user) => { done(err, user); }); }); passport.use(new GoogleStrategy({ clientID: keys.googleClientID, clientSecret: keys.googleClientSecret, callbackURL: '/auth/google/callback' }, (accessToken, refreshToken, profile, done) => { // 整理用户信息,确保后续能正确获取 const user = { token: accessToken, profile: profile, userId: profile.id, userGivenName: profile.name.givenName }; done(null, user); } )); };
验证步骤
- 重启后端服务,确保所有配置生效
- 重新通过Google OAuth完成登录
- 发起AJAX请求,此时后端应该能正确获取到
req.user,认证流程正常执行
内容的提问来源于stack exchange,提问作者Leonard Capacete
相关产品推荐
相关产品推荐

