【问题标题】:Node + Express + Passport: req.user UndefinedNode + Express + Passport:req.user 未定义
【发布时间】:2013-05-02 08:12:42
【问题描述】:

我的问题与这个one类似,但没有深入了解他的解决方案。

我正在使用 Passport 通过 Instagram 进行身份验证。验证成功后,用户被定向到“/”。此时,请求具有用户对象(又名它正在工作)。但是,一旦我重定向, req.user 是未定义的。 :'(

奇怪的是,每个请求都会调用 passport.deserializeUser。它成功地获取了用户对象,但是在中间件的某个地方,req.user 没有被设置(或被取消设置)。

// on successful auth, goto "/" 
app.get('/', function(req, res) {
    // if the request has the user object, go to the user page
    if (req.user) {
        res.redirect("/user/" + req.user._id);
    }

    res.render("index");
}

app.get('/user/:uid', function(req, res) {
    console.log(req.user) // undefined
}

【问题讨论】:

  • 你能发布你的应用程序的配置吗?尤其是中间件 (app.use(...))。可能是您的会话 cookie 过期时间太短,或者您的中间件顺序错误。
  • 中间件排序很可能是这里的问题
  • 我完全按照他们在 Passport 配置页面中解释的方式执行中间件,但仍然面临同样的问题 o.O
  • 您找到解决方案了吗?
  • 我遇到了同样的问题。我无法让它工作,似乎 req.user 每次都被重置

标签: node.js express passport.js


【解决方案1】:

我的问题是在客户端使用 fetch 时没有指定发送 cookie。它在请求中包含凭据后起作用:“包含”字段。

fetch('/api/foo', {credentials: 'include'})

【讨论】:

  • 花了太多时间寻找解决方案,尝试通过各种方式在服务器端配置护照,结果发现问题出在客户端代码中。谢谢你的回答。
  • 等等,这个提示怎么不容易找到??在找到这个之前,我阅读了很多 StackOverflow 问题和答案。谢谢你,乔恩·罗德内斯。谢谢。
  • 花了 4 个小时,又救了我一天左右,也可能是一个月。 :P
  • 稍微扩展一下,cookie 之类的东西只有在请求来自同一个来源时才会默认发送。否则,您必须使用withCredentials 标志来指定您确实希望将cookies 送回。见developer.mozilla.org/en-US/docs/Web/API/Request/credentials。请注意,如果您使用 Axios 之类的东西而不是 fetch API,则语法会有所不同。
【解决方案2】:

您是否为您的应用设置了会话状态?如果你还没有,你需要这样的东西......

app.use(session({ secret: 'anything' }));
app.use(passport.initialize());
app.use(passport.session());

【讨论】:

  • 我完全按照你写的做了,我也收到了undefined 消息。
  • 认为这实际上是app.use(session({secret : 'anything'}); 现在 express-session 是它自己的包而不是 express 的一部分
  • 我在设置表达式后仍然遇到问题。我在初始化 express-session 后调用了护照功能,我可以在应用程序中使用没有问题的会话。
  • @martin 如果我不使用会话,是否需要passport.session()
  • 这个解决方案对我有用,因为我的应用程序配置顺序错误。当我把它们按上面的顺序排列时,问题就解决了。
【解决方案3】:

我是 Node 的超级新手,但对我来说这是一个中间件问题。添加了 bodyParser 并重新排列以修复。

破码:

app.use(express.cookieParser('secret'));
app.use(express.cookieSession());
app.use(express.session({ secret: 'anything' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public'))); 

工作代码:

app.use(express.static(path.join(__dirname, 'public')));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({ secret: 'anything' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);

希望对你有帮助

【讨论】:

  • 这对我有帮助。为什么中间件的第二个顺序起作用而不是第一个?
  • 试图以各种方式调试东西浪费了很多时间,这一切都归结为这一点。将express.static 作为最后一个中间件之一破坏了与我相关的所有身份验证。它甚至不是一致的行为,有时它有效,有时它没有。我怀疑 express / 提到的 libs 代码中的某些内容非常粗略并且容易出现竞争条件。
【解决方案4】:

以前我有这些代码(没有用):

app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser('abcdefg'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(session({
    secret: 'abcdefg',
    resave: true,
    saveUninitialized: false,
    cookie: { secure: true } // this line
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(require('stylus').middleware(path.join(__dirname, 'public')));

然后我从会话初始化程序中删除 cookie 选项:

app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser('abcdefg'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(session({
    secret: 'abcdefg',
    resave: true,
    saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(require('stylus').middleware(path.join(__dirname, 'public')));

现在它可以工作了。

【讨论】:

  • @Squirrl 他的 express 服务器可能位于终止 SSL 连接的代理(Heroku、nginx、IISnode)后面。这很正常。在这里阅读它以获得详细的解释:stackoverflow.com/questions/33871133/…
【解决方案5】:

我遇到了同样的问题,因为我只是从 express-session 文档中复制并粘贴以下代码,但没有完全阅读文档。

app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  cookie: { secure: true }
}))

在文档中,它提到:

但是,它需要启用 https 的网站,即 HTTPS 是 安全 cookie 所必需的。如果设置了安全,并且您访问您的 通过 HTTP 的站点,cookie 将不会被设置。

所以如果你只有一个 HTTP 连接,删除安全选项,下面的代码应该可以工作:

app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  //cookie: { secure: true } remove this line for HTTP connection
}))

【讨论】:

  • 谢谢!我为此花了两个小时绝望,才意识到几个月前我已将 cookie 升级到 HTTPS,并正在通过 HTTP 进行本地测试。
【解决方案6】:

我在使用 express 4 时遇到了同样的问题,在尝试了我在网上能找到的几乎所有东西之后,我终于设法通过添加“cookie-session”来让它工作。

var cookieSession = require('cookie-session');

app.use(cookieSession({
  keys: ['key1', 'key2']
}));

【讨论】:

    【解决方案7】:

    是的,像@Martin 所说的那样启用会话。但如果您使用的是 Express 4.* 版本,会话等中间件未捆绑,因此您需要单独安装。

    1. 在你的 package.json 中添加 "express-session": "1.4.0"
    2. npm 安装
    3. 使用它

    ;

    var express = require('express');
    var cookieParser = require('cookie-parser')
    var session = require('express-session')
    var app = express()
    app.use(cookieParser()) // required before session.
    app.use(session({secret: 'keyboard cat'}))
    

    更多信息请查看express session documentation.

    【讨论】:

    • 根据您链接到的文档,不再推荐使用 Cookie Parser。
    【解决方案8】:

    我认为每个人在服务器端都有几个可能导致这个问题的错误。

    要解决此错误,请检查以下内容:

    检查 1 - Passport 序列化和反序列化

    正确的做法(猫鼬):

    passport.serializeUser((user, done) => {
        done(null, user._id);
    });
    
    passport.deserializeUser((_id, done) => {
      User.findById( _id, (err, user) => {
        if(err){
            done(null, false, {error:err});
        } else {
            done(null, user);
        }
      });
    });
    

    检查 2 - 会话

    检查您的 cookie-session 软件包是否配置正确且正常工作。检查您是否真的可以在客户端看到 cookie。如果您使用的是 express-session,请确保您可以在内存或缓存 (Redis) 中看到 session-id。

    检查 3 - SSL nginx

    确保您的反向代理支持 cookie 和请求类型。不要忘记检查 cookie/会话配置 [secure flag]

    当我遇到这个错误时,我使用 (user) 作为回调函数。然后我用 (err, user) 更正了它。现在没事了。干杯?

    【讨论】:

    • 谢谢!我为此花了两个小时绝望,才意识到几个月前我已将 cookie 升级到 HTTPS,并正在通过 HTTP 进行本地测试。
    【解决方案9】:

    在路由中,尝试添加:{session: true}

    app.get('/auto-login', passport.authenticate('cross', {session: true}))
    

    【讨论】:

    • 刚刚完成,花了大约一个小时调试护照的内部,得出同样的结论。如果您在调用passport.authenticate 的选项中指定session: falsereq.user 将不会被设置。
    • { session: true } 似乎是默认值。
    • 奇怪的是,这对我也有用。护照 v0.3.2。
    • 我正在使用passport-twitter 并且明确设置会话对我不起作用。在同一个应用程序中,执行完全相同的代码行的passport-google-auth 很好。
    【解决方案10】:

    当您对用户进行身份验证时,请求值req.user 被填充。要知道是否识别用户并填写该值,使用 cookie。 如果像我一样,您使用安全 cookie 配置会话,cookie 将仅在 HTTPS 上可用,这不是本地开发服务器的标准配置。要让 cookie 在 HTTP 上工作,注释掉 cookie: { secure: true }req.user 值将被正确配置:

    this.app.use(session({
        resave: true,
        saveUninitialized: true,
        secret: process.env.SESSION_SECRET || "a secret",
        // cookie: { secure: true },
    }));
    

    如果您合理地希望仅在生产环境中使用超过 HTTPS 的 cookie,您可以执行以下操作:

    cookie: { secure: process.env.ENV === 'PRODUCTION' }
    

    【讨论】:

    • 非常感谢!被这个问题困扰了一段时间。
    • 谢谢!我为此花了两个小时绝望,才意识到几个月前我已将 cookie 升级到 HTTPS,并正在通过 HTTP 进行本地测试。
    【解决方案11】:

    我的是关于饼干和软糖的。 我通过将以下代码添加到我的服务器来解决:

    allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', 'http://localhost:3000'); // your website
    res.header('Access-Control-Allow-Credentials', 'true');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
    if ('OPTIONS' === req.method) {
        res.send(200);
    } else {
        next();
    }};
    

    【讨论】:

      【解决方案12】:

      一旦您设置了快速会话,请确保您在生成 req.user 的反序列化函数中进行了护照序列化和反序列化。请参阅另一个 stackoverflow 问题的解释 here

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

      【讨论】:

        【解决方案13】:

        当您在客户端使用 http 请求时,请记住附加凭据。 在 Angular2 中,您需要添加选项参数:{ withCredentials: true }。在此之后,您将拥有相同的 req.sessionID,直到您再次重置它。

        this._http.get("endpoint/something", { withCredentials: true })
        

        【讨论】:

          【解决方案14】:

          在执行passport.authenticate 时,您可以添加session: true 来解决您的问题:

          app.post("/login", passport.authenticate('local', {
              'failureRedirect': '/login',
              'session': true
          }), (req, res)=>{ res.redirect("/"); });
          

          【讨论】:

            【解决方案15】:

            我的与所有这些不同。我之前一直在 localhost 上开发一个 Wordpress 站点,然后切换到一个单独的 Node/React 项目。

            来自 Wordpress 站点的 cookie 仍然存在并正在发送,因为这两个项目都在 localhost 上运行。这是导致问题的原因。

            我必须清除 localhost 的 cookie,然后它才起作用。

            【讨论】:

              【解决方案16】:

              服务器发送 SetCookie 头,然后浏览器句柄来存储它,然后 cookie 与向同一服务器发出的请求一起发送到 Cookie HTTP 头中。

              我必须在我的客户端中设置 withCredentials: true 。 (axios.js)

              const config = {
                withCredentials: true,
                headers: {
                  'Content-Type': 'application/json',
                },
              };
              
              axios.put(url, { page: '123' }, config)
                .then(res => console.log('axios', res))
                .catch(err => console.log('axios', err));
              

              然后出现CORS问题。

              所以我将它添加到我的快递服务器:

              app.use(function(req, res, next) {
                res.header('Access-Control-Allow-Credentials', true);
                res.header('Access-Control-Allow-Origin', req.headers.origin);
                res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
                res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
                if ('OPTIONS' == req.method) {
                  res.send(200);
                } else {
                    next();
                }
              });
              

              【讨论】:

                【解决方案17】:

                'req.user' 仅在 passport.auth 中间件之后才为我设置为用户。我来到这个线程试图找出如何从其他请求中访问用户名(没有 passport.auth 中间件),如果其他人被困在这个问题上,那么试试

                req._passport.session.user;
                

                【讨论】:

                  【解决方案18】:

                  如果您的中间件堆栈不清楚,假设您有会话中间件某处,您可以在重定向之前保存会话:

                  if (req.user) {
                      req.session.save(function (err) {
                          if (err) {
                              // ... panic!
                          }
                          res.redirect("/user/" + req.user._id);
                      });
                      return;
                  }
                  

                  【讨论】:

                    【解决方案19】:

                    您是否尝试在 cookieParser 中插入您的 secretKey?

                    var passport = require('passport');
                    var expressSession = require('express-session');
                    
                    app.use(express.static(path.join(__dirname, 'public')));
                    app.use(cookieParser('mySecretKey'));
                    app.use(bodyParser.json());
                    app.use(bodyParser.urlencoded({ extended: false }));
                    app.use(expressSession({
                    secret: 'mySecretKey',
                      resave: false,
                      saveUninitialized: true
                    }));
                    app.use(passport.initialize());
                    app.use(passport.session());
                    

                    【讨论】:

                      【解决方案20】:

                      遇到了完全相同的问题。对我来说,解决方案是使用“client-sessions”而不是“express-session”。可能是错误的会话配置?

                      不工作的代码:

                      var session = require('express-session');
                      
                      app.use(bodyParser.urlencoded({ extended: false }));
                      app.use(express.static(path.join(__dirname, 'public')));
                      app.use(cookieParser());
                      app.use(bodyParser.json());
                      app.use(session({
                          secret: 'random string',
                          resave: true,
                          saveUninitialized: true,
                          cookie: { secure: true }
                      }));
                      

                      工作代码:

                      var session = require('client-sessions');
                      
                              app.use(bodyParser.urlencoded({ extended: false }));
                              app.use(express.static(path.join(__dirname, 'public')));
                              app.use(cookieParser());
                              app.use(bodyParser.json());
                              app.use(session({
                              cookieName: 'session',
                              secret: 'random string',
                              duration: 30 * 60 * 1000,
                              activeDuration: 5 * 60 * 1000,
                          }));
                      

                      【讨论】:

                        【解决方案21】:

                        我遇到了同样的问题,req.isAuthenticated() 和 req.user,我是这样解决的

                        • req.isAuthenticated() 通过在deserialize()中的findById()方法中用find()替换findOne()来解决,然后我可以保存经过身份验证的req,否则它什么也不返回。

                        • req.user 通过调整顺序解决,首先应该存储快速会话,然后应该初始化护照,然后将下一个会话存储在 passport.session() 中,然后我们可以访问 req.user,在将会话保存在 passport.session() 中之后

                        app.use(session(...));
                        app.use(passport.initialize());
                        app.use(passport.session());
                        // Now we can access req.user so after we will call req.user, if we write it above these, it will always return underfined
                        app.use(function(req, res, next){
                          res.locals.user = req.user || null
                          next();
                        })

                        看看,如果你在passport.session()之后访问req.user,如果没有在下面添加你的路由。

                        【讨论】:

                          【解决方案22】:

                          我的两分钱: 不工作的代码:

                          server.use(
                          session({
                            secret: "secretsssss",
                            rolling: false,
                            resave: false,
                            saveUninitialized: false,
                            cookie: {
                              sameSite: true, //this line
                              maxAge: 60 * 60 * 1000
                            }
                          })
                          );
                          

                          工作代码:

                          server.use(
                          session({
                            secret: "secretsssss",
                            rolling: false,
                            resave: false,
                            saveUninitialized: false,
                            cookie: {
                              sameSite: false, // i think this is default to false
                              maxAge: 60 * 60 * 1000
                            }
                          })
                          );
                          

                          【讨论】:

                            【解决方案23】:

                            遇到了同样的问题,但我的问题更多与在 OAuth 流程和 OAuth 回调路由开始时对 passport.authorizepassport.authenticate 之间的区别的误解有关。

                            passport.authorize 不会影响req.user 变量,但由于我只是从策略文档中复制粘贴了示例代码,因此我没有意识到使用了错误的方法。更改为passport.authenticate 后,用户变量可用。

                            希望这对可能在不知不觉中做同样事情的人有所帮助。

                            【讨论】:

                              【解决方案24】:

                              从此更改顺序:

                              app.set("view engine", "ejs");
                              app.use(bodyParser.urlencoded({ extended: true }));
                              

                              到这里:

                              app.use(bodyParser.urlencoded({ extended: true }));
                              app.set("view engine", "ejs");
                              

                              【讨论】:

                              • 欢迎来到 Stack Overflow。 Stack Overflow 上不鼓励仅使用代码的答案,因为它们没有解释它是如何解决问题的。请编辑您的答案,以说明此更改如何解决问题中的问题,以便它对遇到相同问题的其他用户也有用。
                              【解决方案25】:

                              我正在使用 cookie-parser 和 express-session,如下所示:

                              var express = require("express"); // 4.16.1
                              var cors = require("cors"); // 2.8.5
                              var cookieParser = require("cookie-parser"); // 1.4.4
                              var expressSession = require("express-session"); // 1.17.1
                              
                              var app = express();
                              
                              app.use(
                                cors({
                                  origin: "http://localhost:3000",
                                  credentials: true,
                                })
                              );
                              
                              app.use(express.json());
                              app.use(express.urlencoded({ extended: true }));
                              
                              
                              app.use(
                                expressSession({
                                  secret: "secret123",
                                  resave: true,
                                  saveUninitialized: true,
                                  cookie: { maxAge: 60 * 60 * 24 * 1000 },
                                })
                              );
                              app.use(cookieParser("secret123")); // this line
                              

                              在 express-session 之前放置 cookie-parser 对我有用,如下所示:

                              var express = require("express"); // 4.16.1
                              var cors = require("cors"); // 2.8.5
                              var cookieParser = require("cookie-parser"); // 1.4.4
                              var expressSession = require("express-session"); // 1.17.1
                              
                              var app = express();
                              
                              app.use(
                                cors({
                                  origin: "http://localhost:3000",
                                  credentials: true,
                                })
                              );
                              
                              app.use(express.json());
                              app.use(express.urlencoded({ extended: true }));
                              
                              app.use(cookieParser("secret123"));
                              app.use(
                                expressSession({
                                  secret: "secret123",
                                  resave: true,
                                  saveUninitialized: true,
                                  cookie: { maxAge: 60 * 60 * 24 * 1000 },
                                })
                              );
                              

                              【讨论】:

                                【解决方案26】:

                                我有一个不同的问题,与 bcrpt-node 和箭头函数有关。

                                有效的代码:

                                userSchema.methods.generateHash = function (password) {
                                  return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null); 
                                };
                                
                                userSchema.methods.isValidPassword = function (password) {
                                  return bcrypt.compareSync(password, this.password);
                                };
                                

                                不起作用的代码:

                                userSchema.methods.generateHash = (password) => {
                                  return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
                                };
                                
                                userSchema.methods.isValidPassword = (password) => {
                                  return bcrypt.compareSync(password, this.password);
                                };
                                

                                【讨论】:

                                  猜你喜欢
                                  • 1970-01-01
                                  • 2019-02-19
                                  • 2018-03-28
                                  • 2021-10-26
                                  • 1970-01-01
                                  • 2014-04-30
                                  • 2021-04-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多