req.session.passport 为空,未调用 deserializeUser - ExpressJS,Passport

Posted

技术标签:

【中文标题】req.session.passport 为空,未调用 deserializeUser - ExpressJS,Passport【英文标题】:req.session.passport is empty, deserializeUser not called - ExpressJS, Passport 【发布时间】:2014-11-24 09:59:03 【问题描述】:

我在 Passport/ExpressJS 中使用会话时遇到问题。

当我登录req.session时,我可以看到护照是

 cookie: 
  path: '/',
  _expires: Mon Sep 29 2014 19:37:16 GMT-0300 (BRT),
  originalMaxAge: 3594522,
  httpOnly: true,
  secure: true ,
passport:  

另外,我正在使用 Facebook 进行身份验证,并且没有调用 passport.deserializeUser。 这是我的代码:

    passport.use(new FacebookStrategy(

    // pull in our app id and secret from our auth.js file
    clientID        : configAuth.facebookAuth.clientID,
    clientSecret    : configAuth.facebookAuth.clientSecret,
    callbackURL     : configAuth.facebookAuth.callbackURL

,

// facebook will send back the token and profile
function(token, refreshToken, profile, done) 

    // asynchronous
    process.nextTick(function() 

        console.log("profile " + profile.id);
        console.log("profile.name "+profile.name.givenName)

        // find the user in the database based on their facebook id
        User.findOne( 'facebook.id' : profile.id , function(err, user) 

            // if there is an error, stop everything and return that
            // ie an error connecting to the database
            if (err)
                return done(err);

            // if the user is found, then log them in
            if (user) 
                //returning undefined
                //console.log(user.name + " " + user.email);
                return done(null, user); // user found, return that user
             else 
                // if there is no user found with that facebook id, create them
                var newUser = new User();

                // set all of the facebook information in our user model
                newUser.facebook.id    = profile.id; // set the users facebook id
                newUser.facebook.token = token; // we will save the token that facebook provides to the user
                newUser.facebook.name  = profile.name.givenName + ' ' + profile.name.familyName; // look at the passport user profile to see how names are returned
                newUser.facebook.email = profile.emails[0].value; // facebook can return multiple emails so we'll take the first

                // save our user to the database
                newUser.save(function(err) 
                    if (err)
                        throw err;

                    // if successful, return the new user
                    return done(null, newUser);
                );
            

        );
    );

));

// used to serialize the user for the session
passport.serializeUser(function(user, done) 
    console.log("serialize");
    done(null, user.id);
);

// used to deserialize the user
passport.deserializeUser(function(id, done) 
    console.log("deserialize");
    User.findById(id, function(err, user) 
        console.log(user);
        done(err, user);
    );
);

我尝试将这两种方法移到开头,但没有任何区别。 passport.serializeUser 被调用就好了。

这是我初始化passport的地方:

app.use (cookieParser());
app.use(session( secret: 'appsecret', saveUninitialized: true, cookie:  secure: true, maxAge: new Date(Date.now() + 3600000) , key:'connect.sid' ));

app.use(passport.initialize());
app.use(passport.session());

这是我的route

// =====================================
// FACEBOOK ROUTES =====================
// =====================================
// route for facebook authentication and login

app.get('/auth/facebook', passport.authenticate('facebook',  scope : 'email' ));

// handle the callback after facebook has authenticated the user
app.get('/auth/facebook/callback',
    passport.authenticate('facebook', 
        successRedirect : '/home',
        failureRedirect : '/login'
    ));

有人可以帮我解决这个问题吗?

谢谢!

【问题讨论】:

您能告诉我们初始化 Passport 的代码吗?人们经常忘记初始化它,或者以错误的顺序执行它。它应该像这样初始化:app.use(express.session( secret: 'keyboard cat' )); app.use(passport.initialize()); app.use(passport.session()); 另外,你能告诉我们认证路径的代码吗? 已在问题中编辑 :) 好的,对我来说一切都很好。愚蠢的问题:您说注销req.sessionpassport为空。你在哪里(在代码中)做的?另外,您说 passport.serializeUser 被调用就好了。,但是当您尝试记录 user 参数时会发生什么? 我在app.get('/home')中注销,这是认证成功时调用的路由。用户未定义 @LarissaLeite 你解决了吗? 【参考方案1】:

背景

对我来说,没有调用 deserializeUser 和空护照对象的问题是跨域问题。当我从 localhost:4200 向 localhost:1000 发送 ajax 请求时,cookie 和会话对我的 Ember.js 客户端不起作用。但是,邮递员分机收到了正确的响应。护照对象也正确填写了数据。 User.deserializeUser 被正确调用。

解决方案

为了解决这个问题,我必须设置正确的服务器端和客户端 HTTP 标头。 服务器端(node.js + express + passport):

# The important part. Must go AFTER the express session is initialized
app.use passport.initialize()
app.use passport.session()

# Enable CORS
# X-Requested-With, X-AUTHENTICATION, X-IP
# https://***.com/a/18290875/2166409
app.use (req, res, next) ->
  res.header 'Access-Control-Allow-Origin', 'http://localhost:4200'
  res.header 'Access-Control-Allow-Headers', 'Origin, X-Requested-With, X-AUTHENTICATION, X-IP, Content-Type, Accept'
  res.header 'Access-Control-Allow-Credentials', true
  res.header 'Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'
  next()

app.use '/api/v1', router

客户端:

如果使用 jQuery,请将其添加到 $.ajax 选项中:

xhrFields:  withCredentials:true 

然后一切都按预期工作:

DESERIALIZE USER
 id: '547fabf22a098ade53e6e48e',
  name: 'test',
  firstName: 'test',
  email: 'test@wp.pl' 
LOGIN SUCCESS SESSION
 cookie: 
    path: '/',
     _expires: Thu Dec 04 2014 20:26:52 GMT+0100 (CET),
     originalMaxAge: 3597205,
     httpOnly: false ,
  passport: 
    user: 
       id: '547fabf22a098ade53e6e48e',
        name: 'test',
        firstName: 'test',
        email: 'test@wp.pl'   

这些答案帮助了我:about Ember.js、jQuery.ajax。

【讨论】:

您可以通过查看 js 控制台查看是否存在 cors 问题,然后在浏览器上使用 --disable-web-security 标志在开发中解决它。【参考方案2】:

我的解决方案是在链接我网站的不同页面时保持一致。

在链接的 URL 前加上“www”。同时验证没有“www”的地方。链接到该前缀页面时将启动一个新会话。 您可以使用 cookie 查看器进行检查,看看这两个选项中的每一个是否有多个 cookie。

【讨论】:

【参考方案3】:

对我来说,根本原因是 express-session 中的 cookie 安全值。

app.use(require('express-session')(
    secret: 'crackalackin',
    resave: true,
    saveUninitialized: true,
    cookie :  secure : false, maxAge : (4 * 60 * 60 * 1000) , // 4 hours
));

在我的本地机器上,我没有通过 HTTPs 运行,所以当 cookie.secure 为 true 时,会话和用户对象为空。当处于开发模式且安全为 false 时,它​​可以正常工作。

【讨论】:

经过数小时的搜索,这为我解决了!谢谢! 我只花了 1 小时的时间搜索,但这仍然为我解决了这个问题,谢谢! 你是我的救星!谢谢,格雷格,我尝试禁用 cors,但没有奏效,但您的解决方案效果很好。

以上是关于req.session.passport 为空,未调用 deserializeUser - ExpressJS,Passport的主要内容,如果未能解决你的问题,请参考以下文章

对象可能为空或未定义 [重复]

NodeJS - 如何检查 MySQL 结果是不是未定义/为空?

源为空/未定义时的 KnockoutJS 绑定

VBA DAO.Recordset 在尝试关闭它时为空或未设置 - 但我事先检查它是不是为空

如何确定中继查询是不是为空或未加载

当数据未定义或为空时如何使用 Lodash