用户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有两个原因:
-
恕我直言打破连接authentication非常强大和易于阅读洋葱环连接的体系结构。 一个不走 – 我的意见:)。 你可以在这里find一篇关于连接工作和洋葱圈理念的非常好的短文章。
-
如果你写 – 只是想用数据库或文件的基本或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-based-strategy
我正在使用express [ http://expressjs.com ],所以连接插件非常适合,因为express是从分类(ok – prototyped)连接
我基本上是在寻找同样的事情。 具体来说,我想要以下几点:
- 使用express.js,它包装了Connect的中间件function
- “基于表单”身份validation
- 对哪些路由进行身份validation的细粒度控制
- 用户/密码的数据库后端
- 使用会话
我最终做的是创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。 只有
username
和password
。 - 它可以与多个数据库(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:
使用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
披露:我是这个图书馆的开发者。