在nodejs身份验证中使用passport的findById的替代方案?

时间:2014-09-02 02:02:23

标签: javascript node.js express passport.js

我使用护照来验证用户身份。我的node.js服务器作为另一台服务器的代理服务器工作;我可以向其他服务器发送验证请求,以验证用户和密码是否正确。

我在我的deserializeUser中需要包含的函数有问题,因为其他服务器不包含任何通过id搜索给定用户的方法。

首先,这是我的序列化和反序列化函数。请注意,我使用用户名作为我的标识符。

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

//used to deserialize the user from the session
passport.deserializeUser(function(username, done) {
    user.findByUsername(username, function(err, user) {
        done(err, user);
    });
});

对于本地策略,这是我的代码:

passport.use('local-login', new LocalStrategy({
    //use the fields for username and password
    usernameField : 'username',
    passwordField : 'password',
    passReqToCallback : true
},
function(req, username, password, done) {
    var loginUser  = new User('username', 'password');
    loginUser.authenticate(function(err, user) {
        if(!user)
            return done(null, false, req.flash('loginMessage', 'No user found.'));

        return done(null, user);
}));

authenticate函数定义如下(为简洁起见,包括伪代码):

function(callback) {
    //make a call to the external server with this.username and this.password as credentials
    //if error
    callback(err, null)
    //if the external server verifies the call,
    callback(null, user)
}

我应该在deserializeUser中使用什么?

另外,我甚至不理解为什么deserializeUser需要一个用户对象。是不是只从会话中提取用户?或者这是我的一个根本误解?

1 个答案:

答案 0 :(得分:2)

deserializeUser函数获取用户标识符(存储在会话中),并使用它来从用户存储中获取完整的用户对象,以便填充快速请求对象的用户成员。

这很有用,因为您可能不希望在会话中存储完整的用户对象,只是对它的引用,然后您可以在每个请求中从数据库或其他用户存储中获取完整对象

使用serializeUserdeserializeUser中的标识符的用户名似乎应该有效,只要标识符在两者之间保持一致。

至于将用户对象序列化到单独的商店之外 - 该用户对象的内容主要用于您的方便。如果你的某些路线中有代码需要检查用户的某些属性,那么这就是放置它的地方。如果您的代码不需要知道除了有效用户之外的其他任何内容,那么您的用户对象可以只是{username: username}

-

因此,在您的示例中,您提到您的外部服务器只能验证用户名和密码是否正确,并为您提供令牌。如果您没有关于用户的其他单独信息存储,这意味着您的应用程序要保留的关于用户的唯一信息是他们已经过身份验证以及他们的用户名和令牌是什么。

然后你的本地策略看起来像:

passport.use('local-login', new LocalStrategy({ 
    //use the fields for username and password 
    usernameField : 'username', 
    passwordField : 'password', 
    passReqToCallback : true 
  }, 
  function(req, username, password, done) { 
    somehowAuthenticateWithMyExternalServer(username, password, function(isValid, token) { 
    if(!isValid) 
      return done(null, false, req.flash('loginMessage', 'No user found.')); 
    return done(null, { username: username, token: token }); 
  }); 
}));

由于您只想将此用户对象保留在会话中而不是在任何地方将其序列化,因此您的序列化/反序列化函数可能只是简单的传递:

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

//used to deserialize the user from the session 
passport.deserializeUser(function(user, done) { 
    done(null, user); 
});

(也许在这种情况下可以省略这些,不确定)

然后,如果您的任何路线在req.user对象上进行检查,则其唯一的属性将是username和'令牌。