2017-10-18 67 views
0

我已经阅读了所有论点,但仍然无法理解它。 Passport Js网站上的文档非常含糊。Passport js serializeUser&deserializeUser

我正在使用护照JS与Passport-ldapauth策略。 我没有一个数据库我明显不希望在每个请求中都访问LDAP服务器。我想在POST /login路由上第一次使用带LDAP的护照策略对用户进行身份验证,将用户存储在会话中以及每个后续请求上,我只想检查用户是否已登录。

我想使用会话,但我不明白如何使用Passport +会话与序列化/反序列化流程。 我检查的每个示例都使用deserializeUser函数中的User.findOne。

截至目前,我禁用了Passport会话的使用,并且我正在使用自定义中间件来检查是否req.session.user != null。如果是这种情况,用户已经登录,我打next()。否则重定向到登录。

下面是一些代码(为简单起见,我删除不相关的问题的代码):

护照配置

var express = require('express'), 
    session = require('express-session'), 
    passport = require('passport'), 
    LdapStrategy = require('passport-ldapauth'); 

var app = express(); 

var LdapStrategyOptions = { 
    server: { 
    url: '<url>', 
    bindDN: '<dn>', 
    bindCredentials: "<pwd>", 
    searchBase: '<searchBase>', 
    searchFilter: '<filter>' 
    } 
}; 
passport.use(new LdapStrategy(LdapStrategyOptions)); 

app.use(cookieParser()); 
app.use(session({ 
    store: new LokiStore({autosave: false}), 
    resave: false, 
    saveUninitialized: false 
    secret: env.get("SESSION_SECRET") 
})); 

app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded({ extended: false })); 

app.use(passport.initialize()); 

路线

// LOGIN ROUTE 
app.get('/login', 
    function(req, res) { 
    res.render('login'); 
}); 

// LOGIN HANDLER ROUTE 
app.post('/login', 
    passport.authenticate('ldapauth', { session: false }), 
    function(req, res) { 
    req.session.userId = req.user.cn; 
    req.session.user = { 
     "userId": req.user.cn, 
     "displayName": req.user.displayName 
    }; 
    res.redirect('/'); 
}); 

// LOGOUT ROUTE 
app.get('/logout', 
    function(req, res) { 
    req.session.destroy(function(err) { 
     req.logout(); 
     res.redirect('/'); 
    }); 
}); 

// HOME ROUTE 
app.get('/', isLoggedIn, function(req, res) { 
    res.render('home'); 
}); 

IsLoggedIn中间件

var isLoggedIn = function(req, res, next) { 
    if (req.session.user != null){ 
    console.log("is auth ok '" + req.session.user.userId +"'"); 
    return next(); 
    } 

    console.log("redirect to auth/login"); 
    res.redirect('/auth/login'); 
} 

我在想什么?我的设置中是否存在安全问题? 任何帮助表示赞赏。

+0

是否有可能你缺少'app.use(passport.session());'? –

+0

没有。我从示例代码中删除了它,因为我写的是,我没有使用它,因为我不明白我应该在passport.deserializeUser()中写什么。 示例cose就是我发现的使自定义会话管理工作的方式。 – Roberto

回答

0

passportjs文档:

在典型的网络应用程序中,用于验证用户的凭证将仅登录请求期间发送。如果验证成功,会话将通过用户浏览器中设置的cookie建立和维护。

每个后续请求将不包含凭据,而是标识会话的唯一cookie。为了支持登录会话,Passport将序列化和反序列化会话中的用户实例。

基本上serializeUser应该返回一个唯一的用户标识,以便以后可以deserializeUser回JSON。

因此,对于你实现你或许应该做一些沿着这些路线:

免责声明:我与LDAP没有经验。

passport.serializeUser(function(user, done) { 
    //We can identify the user uniquely by the CN, 
    //so we only serialize this into the session token. 
    done(null, user.cn); 
}); 

passport.deserializeUser(function(cn, done) { 
    //Directly query LDAP. 
    //I'm not sure passport caches the result (only calls deserializeUser for new sessions) 
    //but worst case you can cache the result yourself. 
    somehowLoadUserFromLDAPByCN(cn, function(err, user) { 
    done(err, { 
    userId: user.cn, 
    displayName: user.displayName 
    }); 
    }); 
}); 
+0

Exaclty!但问题是我不想在每个请求中都使用LDAP(资源密集型进程)。数据库也是如此。为什么我应该在每个请求上对数据库进行查询?这正是我在护照​​框架中不了解的。 – Roberto

+0

我不记得护照是否处理缓存这个函数的结果。你可以通过设置一个断点来检查你自己,看看它是否在你已经被认证时被调用。我的假设是它没有(因为passport不知道你是否想要缓存这些结果,你可以将结果自己缓存在这个函数中,并且只有在缓存未命中的情况下才能访问LDAP查询)。缓存的实现取决于您(内存中,redis等)。 –

+0

即使您已经过身份验证,也会在每个请求上调用deserializeUser。我仍然无法得到这个功能的目的。为什么我应该在每个请求上点击授权系统(DB,LDAP,Facebook服务)?为什么我应该将用户配置文件缓存在数据库中?如果我可以使用该会话存储用户名,电子邮件和这些内容? – Roberto

1

如果您只需要一个id和一个显示名称,将它们保留在会话中是完全正常的。您只需加载完整的用户配置文件,当你需要更多的领域。

相关问题