用户authentication库为node.js?

是否有任何现有的用户authentication库node.js? 特别是我正在寻找一些可以为用户进行密码validation(使用自定义后端validation数据库),并将该用户与会话相关联。

在我写一个auth库之前,我想我会看看大家是否知道现有的库。 通过谷歌search找不到任何明显的东西。

-Shreyas

如果您正在寻找Connect或Expressauthentication框架,Passport值得深入研究: https : //github.com/jaredhanson/passport

(披露:我是Passport的开发者)

在调查connect-auth和everyauth之后,我开发了Passport。 虽然他们都是很好的模块,但并不适合我的需求。 我想要的东西更轻盈,不显眼。

护照分解成单独的模块,所以你可以select只使用你需要的(OAuth,只有在必要时)。 Passport在应用程序中也不会安装任何路由,使您可以灵活地决定何时何地进行身份validation,还可以使用挂接来控制身份validation成功或失败时发生的情况。

例如,以下是设置基于表单(用户名和密码)authentication的两步过程:

 passport.use(new LocalStrategy( function(username, password, done) { // Find the user from your DB (MongoDB, CouchDB, other...) User.findOne({ username: username, password: password }, function (err, user) { done(err, user); }); } )); app.post('/login', passport.authenticate('local', { failureRedirect: '/login' }), function(req, res) { // Authentication successful. Redirect home. res.redirect('/'); }); 

其他策略可通过Facebook,Twitter等进行身份validation。如有必要,可以插入自定义策略。

会话+如果

我猜你没有find很多好的库的原因是使用库进行身份validation主要是工程。

你正在寻找的只是一个会话绑定:)会话与:

 if login and user == xxx and pwd == xxx then store an authenticated=true into the session if logout destroy session 

而已。


我不同意你的结论,connect-auth插件是要走的路。

我正在使用也连接,但我不使用connect-auth有两个原因:

  1. 恕我直言打破连接authentication非常强大和易于阅读洋葱环连接的体系结构。 一个不走 – 我的意见:)。 你可以在这里find一篇关于连接工作和洋葱圈理念的非常好的短文章。

  2. 如果你写 – 只是想用数据库或文件的基本或httplogin。 Connect-auth太大了。 这更像是OAuth 1.0,OAuth 2.0&Co等


连接的一个非常简单的authentication

(它是完整的,只是执​​行它进行testing,但如果你想在生产中使用它,一定要使用https)(而要成为REST原则兼容,你应该使用POST请求,而不是一个GET请求B / C你改变状态:)

 var connect = require('connect'); var urlparser = require('url'); var authCheck = function (req, res, next) { url = req.urlp = urlparser.parse(req.url, true); // #### // Logout if ( url.pathname == "/logout" ) { req.session.destroy(); } // #### // Is User already validated? if (req.session && req.session.auth == true) { next(); // stop here and pass to the next onion ring of connect return; } // ######## // Auth - Replace this example with your Database, Auth-File or other things // If Database, you need a Async callback... if ( url.pathname == "/login" && url.query.name == "max" && url.query.pwd == "herewego" ) { req.session.auth = true; next(); return; } // #### // This user is not authorized. Stop talking to him. res.writeHead(403); res.end('Sorry you are not authorized.\n\nFor a login use: /login?name=max&pwd=herewego'); return; } var helloWorldContent = function (req, res, next) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('authorized. Walk around :) or use /logout to leave\n\nYou are currently at '+req.urlp.pathname); } var server = connect.createServer( connect.logger({ format: ':method :url' }), connect.cookieParser(), connect.session({ secret: 'foobar' }), connect.bodyParser(), authCheck, helloWorldContent ); server.listen(3000); 

注意

我在一年前写了这个声明,目前没有活动的节点项目。 所以在Express中可能会有API-Changes。 如果我应该改变任何东西,请添加评论。

看起来连接中间件的connect-auth插件正是我所需要的: http : //wiki.github.com/ciaranj/connect-auth/creating-a-form-b​​ased-strategy

我正在使用express [ http://expressjs.com ],所以连接插件非常适合,因为express是从分类(ok – prototyped)连接

我基本上是在寻找同样的事情。 具体来说,我想要以下几点:

  1. 使用express.js,它包装了Connect的中间件function
  2. “基于表单”身份validation
  3. 对哪些路由进行身份validation的细粒度控制
  4. 用户/密码的数据库后端
  5. 使用会话

我最终做的是创build我自己的中间件函数check_auth ,我将其作为parameter passing给我要validation的每个路由。 check_auth只是检查会话,如果用户没有login,则将其redirect到login页面,如下所示:

 function check_auth(req, res, next) { // if the user isn't logged in, redirect them to a login page if(!req.session.login) { res.redirect("/login"); return; // the buck stops here... we do not call next(), because // we don't want to proceed; instead we want to show a login page } // the user is logged in, so call next() next(); } 

那么对于每个路由,我确保这个函数作为中间件传递。 例如:

 app.get('/tasks', check_auth, function(req, res) { // snip }); 

最后,我们需要实际处理login过程。 这很简单:

 app.get('/login', function(req, res) { res.render("login", {layout:false}); }); app.post('/login', function(req, res) { // here, I'm using mongoose.js to search for the user in mongodb var user_query = UserModel.findOne({email:req.body.email}, function(err, user){ if(err) { res.render("login", {layout:false, locals:{ error:err } }); return; } if(!user || user.password != req.body.password) { res.render("login", {layout:false, locals:{ error:"Invalid login!", email:req.body.email } } ); } else { // successful login; store the session info req.session.login = req.body.email; res.redirect("/"); } }); }); 

无论如何,这种方法的devise大都是灵活而简单的。 我相信有很多方法可以改进它。 如果有的话,我非常喜欢你的反馈。

编辑:这是一个简单的例子。 在生产系统中,您绝对不想以纯文本存储和比较密码。 正如一位评论者指出的那样,有些库可以帮助pipe理密码安全。

如果你想要第三方/社交networkinglogin集成,也可以看看everyauth 。

这里是我的一个项目的基本authentication的一些代码。 我用它与CouchDB和额外的authentication数据caching,但我剥夺了代码。

将请求处理的身份validation方法包装起来,并为未成功的身份validation提供第二个callback。 成功callback将获得用户名作为额外的参数。 不要忘记在失败callback中正确处理错误或缺less凭据的请求:

 /** * Authenticate a request against this authentication instance. * * @param request * @param failureCallback * @param successCallback * @return */ Auth.prototype.authenticate = function(request, failureCallback, successCallback) { var requestUsername = ""; var requestPassword = ""; if (!request.headers['authorization']) { failureCallback(); } else { var auth = this._decodeBase64(request.headers['authorization']); if (auth) { requestUsername = auth.username; requestPassword = auth.password; } else { failureCallback(); } } //TODO: Query your database (don't forget to do so async) db.query( function(result) { if (result.username == requestUsername && result.password == requestPassword) { successCallback(requestUsername); } else { failureCallback(); } }); }; /** * Internal method for extracting username and password out of a Basic * Authentication header field. * * @param headerValue * @return */ Auth.prototype._decodeBase64 = function(headerValue) { var value; if (value = headerValue.match("^Basic\\s([A-Za-z0-9+/=]+)$")) { var auth = (new Buffer(value[1] || "", "base64")).toString("ascii"); return { username : auth.slice(0, auth.indexOf(':')), password : auth.slice(auth.indexOf(':') + 1, auth.length) }; } else { return null; } }; 

几年过去了,我想介绍一下我的Expressauthentication解决scheme。 这就是所谓的Lockit 。 你可以在GitHub上find这个项目,在我的博客上find一个简短的介绍。

那么现有的解决scheme有什么不同呢?

  • 易于使用:设置您的数据库,npm安装, require('lockit')lockit(app) ,完成
  • 已经内置的路线(/注册,/login,/忘记密码等)
  • 已经内置的视图(基于Bootstrap,但您可以轻松使用自己的视图)
  • 它支持您的AngularJS / Ember.js单页应用程序的JSON通信
  • 它不支持OAuth和OpenID。 只有usernamepassword
  • 它可以与多个数据库(CouchDB,MongoDB,SQL)一起使用
  • 它有testing(我找不到Drywall的任何testing)
  • 它是积极维护(相比everyauth)
  • 电子邮件validation和忘记密码处理(发送带有令牌的电子邮件,不受护照支持)
  • 模块化:只使用你需要的东西
  • 灵活性:定制所有的东西

看看例子 。

不同的authentication方式是无密码,一种基于令牌的快速authentication模块,它避开了密码的固有问题[1]。 它的实现速度很快,不需要太多的表单,并为普通用户提供更好的安全性(完全公开:我是作者)。

[1]: 密码已过时

有一个名为Drywall的项目,通过Passport实现用户login系统,还有一个用户pipe理pipe理面板。 如果你正在寻找一个function齐全的用户authentication和pipe理系统,类似于Django,但是Node.js,这就是它。 我发现它是构build需要用户身份validation和pipe理系统的节点应用程序的非常好的起点。 关于护照如何工作的信息见Jared Hanson的答案 。

这里有两个stream行的Github库,用于节点jsauthentication:

https://github.com/jaredhanson/passport(suggestible

https://nodejsmodules.org/pkg/everyauth

使用mongo的简单例子,提供了一个为Angular客户端提供用户authentication的API

在app.js中

 var express = require('express'); var MongoStore = require('connect-mongo')(express); // ... app.use(express.cookieParser()); // obviously change db settings to suit app.use(express.session({ secret: 'blah1234', store: new MongoStore({ db: 'dbname', host: 'localhost', port: 27017 }) })); app.use(app.router); 

为你的路线这样的事情:

 // (mongo connection stuff) exports.login = function(req, res) { var email = req.body.email; // use bcrypt in production for password hashing var password = req.body.password; db.collection('users', function(err, collection) { collection.findOne({'email': email, 'password': password}, function(err, user) { if (err) { res.send(500); } else { if(user !== null) { req.session.user = user; res.send(200); } else { res.send(401); } } }); }); }; 

然后在需要auth的路由中,您可以检查用户会话:

 if (!req.session.user) { res.send(403); } 

这是一个使用时间戳标记的新的身份validation库。 令牌可以通过电子邮件发送或发送给用户,而无需将其存储在数据库中。 它可以用于无密码身份validation或双因素身份validation。

https://github.com/vote539/easy-no-password

披露:我是这个图书馆的开发者。