具有“持久性标记”function的Node.js身份validation库

我有一个节点护照的工作知识,但它没有如下的东西:

  • 生成一个“持久性标记”(例如在authlogic / session / session.rb#L35中)
  • 生成密码重置的易腐标记
  • 记住我的function
  • pipe理某些模型类的login/注销的属性等。

有没有在Node.js社区解决这个问题的库? 如果有什么像Rails的Rails那样健壮(或者说它的强大),那将是完美的,但是解决这个令牌问题的任何东西都可以起作用。

疯狂的事情是很多的例子存储在会话中的用户id

 request.session['userId'] = user.get('id') 

这只是要求被黑客入侵。

它应该是这样的:

 require.session['persistenceToken'] = App.User.generateRandomToken() 

用于密码重置的一次性密码(又名一次性令牌)策略是我将要实施的。 鉴于护照的架构,这可以很容易地成为一个单独的模块,并不意外发现别人已经实现了这样的事情。

记住我和持久性令牌function也是我想支持的。 最好是,我希望这是一个单独的战略,但它可能需要一些核心支持。 如果事实如此, req.logInhttps://github.com/jaredhanson/passport/blob/master/lib/passport/http/request.js#L28 )中的一些额外的行应该能够覆盖它。

至于在会话中存储用户ID,我没有看到任何大的风险,因为在Connect / Express默认情况下,会话属性完全存储在后端,并通过在encryption的cookie中设置的唯一sid查找。 恶意用户必须拥有唯一的sid和会话密钥才能欺骗请求。

Mozilla使用Passport作为其身份工作的一部分,以将BrowserID与其他缺乏BrowserID支持的提供者(请参阅browserid-bigtent )相连接。 考虑到他们的要求,开发人员可以确定Passport符合严格的安全要求。

(最终,Passport中的会话序列化是应用程序的责任,所以如果出于安全原因需要使用随机令牌来替代用户ID,显然这应该在将数据直接存储在cookie中的情况下完成,但是我build议这是最不明智的做法。)

至于在模型上pipe理这些属性,Passport被devise为完全模型/ ORM不可知的。 我不打算改变这个事实,因为我认为这些决定最好留给申请人(由于授权这个责任,护照更加灵活)。 也就是说,我认为还有其他模块可以独立构build在Passport之上来提供这个function。

所有这一切,我认为Passport是现有的Node.jsauthentication解决scheme中最强大的。 你的前三个要求将会使得它变得更加完善,而且应该很容易完成。 我很乐意合作获取这些function,所以不要犹豫与我联系。

最后,如果有人感到好奇,一级APIauthentication目前正在工作中,在authinfo分支上。 在此基础上, passport-http-oauth实现了OAuth服务器策略,该策略可以与oauthorize middlware结合作为工具包来组装OAuth服务器。 这还没有完全烘焙,但它准备好后,它将是护照的另一个有效function。

同时,像下面这样的东西就足够了。 根据需要进行调整以适应您的应用程序和所需的Cookie时长 检查用户名和密码是一种简单的方式来检测login尝试,但它与护照运作良好。

 app.use(function(req, res, next) { if( typeof(req.body.username) !== "undefined" && typeof(req.body.password) !== "undefined" ) { if(req.body.remember == 1) { req.session.cookie.maxAge = 365*24*60*60*1000; } else { req.session.cookie.maxAge = 24*60*60*1000; } } next(); }); 

虽然我一定希望在passport.js中看到这些function,但它们还不在那里。

我已经创build了一个简单的随机标记生成器来与passport.js serilizeUser()函数一起使用,并修改了Justen的答案,以适应我的需要。 基本上,唯一的区别是,如果没有设置“记住”选项,只要浏览器打开,会话就会持续。

这是我的随机访问令牌生成器的串行器。 我正在使用Mongodb和Mongoose,但实现应该转换到其他系统相当好。

基本上,我得到的时间和附加一个随机的16个字符的string。 然后,在serializeUser()函数中,我检查没有其他用户具有相同的标记(标记应该是唯一的!)。

 User.methods.generateRandomToken = function () { var user = this, chars = "_!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", token = new Date().getTime() + '_'; for ( var x = 0; x < 16; x++ ) { var i = Math.floor( Math.random() * 62 ); token += chars.charAt( i ); } return token; }; 

这里是序列化程序:

 passport.serializeUser( function ( user, done ) { var createAccessToken = function () { var token = user.generateRandomToken(); app.User.findOne( { accessToken: token }, function (err, existingUser) { if (err) return done( err ); if (existingUser) createAccessToken(); // Run the function again - the token has to be unique! else { user.set( 'accessToken', token ); user.save( function ( err ) { if (err) return done( err ); return done( null, user.get('accessToken') ); }) } }); }; if ( user._id ) { createAccessToken(); } }); 

…这是我处理“记住我”function的中间件版本。 不过,我宁愿将它作为serializeUser函数或passport.js核心的一部分。

 app.use( express.session( { secret: 'secret_key' } ) ); app.use( function (req, res, next) { if ( req.method == 'POST' && req.url == '/login' ) { if ( req.body.remember ) { req.session.cookie.maxAge = 30*24*60*60*1000; // Rememeber 'me' for 30 days } else { req.session.cookie.expires = false; } } next(); }); app.use( passport.initialize() ); app.use( passport.session() ); 

我希望能有所帮助。 我花了几个小时才弄明白,我不太确定这是做到这一点的最好方法,但现在对我来说却是有效的。