当前位置:  开发笔记 > 编程语言 > 正文

node.js的用户身份验证库?

如何解决《node.js的用户身份验证库?》经验,为你挑选了6个好方法。

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

在我写一个auth库之前,我想我会看看人们是否知道现有的库.通过谷歌搜索找不到任何明显的东西.

-Shreyas



1> Jared Hanson..:

如果您正在寻找Connect或Express的身份验证框架,Passport值得研究:https://github.com/jaredhanson/passport

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

我在调查了connect-auth和everyauth后开发了Passport.虽然它们都是很棒的模块,但它们并不适合我的需求.我想要的东西更轻盈,不引人注目.

Passport被分解为单独的模块,因此您可以选择仅使用您需要的内容(仅在必要时使用OAuth).Passport也不会在您的应用程序中安装任何路由,使您可以灵活地决定何时何地进行身份验证,并可以通过挂钩来控制身份验证成功或失败时发生的情况.

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

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等进行身份验证.如有必要,可以插入自定义策略.



2> Matthias..:

会话+如果

我想你没有找到很多好的库的原因是使用库进行身份验证主要是过度设计的.

您正在寻找的只是一个会话活页夹:)一个会话:

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

而已.


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

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

    恕我直言打破connect-auth非常强大且易于阅读的洋葱圈连接架构.禁止 - 我的意见:).你可以找到关于如何连接工作非常好,短文章和洋葱圈的想法在这里.

    如果你 - 正如所写 - 只想使用数据库或文件的基本或http登录.Connect-auth太大了.对于像OAuth 1.0,OAuth 2.0&Co这样的东西更多


一个非常简单的连接验证

(它是完整的.只需执行它进行测试,但如果你想在生产中使用它,请确保使用https)(并且要符合REST原则,你应该使用POST-Request而不是GET-Request 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更改.如果我要更改任何内容,请添加评论.


这仍然无法回答如何连接到数据库后端(最好使用加密密码).我很感激你的评论,这个库是过度设计的,但肯定有一个不是.另外,如果我想编写自己的auth系统,我会在Java中使用Struts.就像OP一样,我想知道哪些插件会在一行代码中为我做这件事.
非常好的答案Nivoc.不适用于最新版本的连接.我不得不改变... cookieDecoder() - > cookieParser()和bodyDecoder() - > bodyParser()并从helloWorldContent函数中删除next()调用,因为我收到错误'无法在它们之后设置标题发送'
是.它必须使用next()因为这就是连接背后的想法.Connect具有层结构/形式的代码结构.并且每个层都有权通过不调用next()来停止请求执行.如果我们谈论身份验证:身份验证层将检查用户是否具有正确的权限.如果一切都很好,图层会调用next().如果不是,则此auth层会生成错误,并且不会调用next().

3> shreddd..:

Looks like the connect-auth plugin to the connect middleware is exactly what I need: http://wiki.github.com/ciaranj/connect-auth/creating-a-form-based-strategy

I'm using express [ http://expressjs.com ] so the connect plugin fits in very nicely since express is subclassed (ok - prototyped) from connect



4> Tom..:

我基本上都在寻找相同的东西.具体来说,我想要以下内容:

    使用包含Connect中间件功能的express.js

    "基于表单"的身份验证

    精确控制对哪些路由进行身份验证

    用户/密码的数据库后端

    使用会话

我最终做的是创建我自己的中间件函数check_auth,我将其作为参数传递给我想要验证的每个路由.check_auth仅检查会话以及用户是否未登录,然后将其重定向到登录页面,如下所示:

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
});

最后,我们需要实际处理登录过程.这很简单:

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("/");
    }
  });
});

无论如何,这种方法主要是为了灵活和简单.我确信有很多方法可以改进它.如果你有,我非常希望你的反馈.

编辑:这是一个简化的例子.在生产系统中,您永远不想以纯文本形式存储和比较密码.正如评论者指出的那样,有一些lib可以帮助管理密码安全性.


这很好,除了你应该使用bcrypt存储密码(不是db中的纯文本).这里有一篇很好的帖子:http://devsmash.com/blog/password-authentication-with-mongoose-and-bcrypt

5> Peter Lyons..:

如果您想要第三方/社交网络登录集成,还可以查看Everyauth.



6> b_erb..:

以下是我的一个项目的基本身份验证代码.我使用它与CouchDB和额外的auth数据缓存,但我剥离了该代码.

围绕您的请求处理包装身份验证方法,并为不成功的身份验证提供第二个回调.成功回调将获取用户名作为附加参数.不要忘记在故障回调中正确处理错误或丢失凭据的请求:

/**
 * 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;
    }

};

推荐阅读
依然-狠幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有