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

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);
    }
  ));
};
验证步骤
  1. 重启后端服务,确保所有配置生效
  2. 重新通过Google OAuth完成登录
  3. 发起AJAX请求,此时后端应该能正确获取到req.user,认证流程正常执行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:11:50