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

在我编写一个认证库之前,我想看看人们是否知道现有的库。在谷歌上找不到明显的东西。

-Shreyas


当前回答

下面是我的一个项目中的一些基本身份验证代码。我使用它来对付CouchDB和额外的认证数据缓存,但我剥离了这些代码。

在请求处理周围包装一个身份验证方法,并为身份验证不成功提供第二个回调。成功回调将获得用户名作为附加参数。不要忘记在失败回调中正确处理错误或缺少凭据的请求:

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

};

其他回答

如果你想要第三方/社交网络登录集成,也要看看每个auth。

slim-auth

轻量级、零配置的用户认证模块。它不需要单独的数据库。

https://www.npmjs.com/package/slimauth

很简单:

app.get('/private-page', (req, res) => {

    if (req.user.isAuthorized) {
        // user is logged in! send the requested page
        // you can access req.user.email
    }
    else {
        // user not logged in. redirect to login page
    }
})

对身份验证的另一种理解是passdless,这是express的一个基于令牌的身份验证模块,它绕过了密码[1]的固有问题。它实现起来很快,不需要太多表单,并且为普通用户提供了更好的安全性(完全披露:我是作者)。

[1]:密码过时

关于手摇方法,要注意一点:

我很失望地看到,本文中建议的一些代码示例并不能防止会话固定或定时攻击等基本身份验证漏洞。

与这里的一些建议相反,身份验证并不简单,处理解决方案也不总是简单的。我推荐passsportjs和bcrypt。

但是,如果你决定着手解决问题,可以看看express js提供的例子,以获得灵感。

祝你好运。

会话+ If

我想,您没有找到很多好的库的原因是,使用库进行身份验证在很大程度上是过度设计的。

你要找的只是一个会话绑定器:)一个会话:

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

这是它。


我不同意你认为connect-auth插件是正确的选择的结论。

我也使用连接,但我不使用连接认证的原因有两个:

IMHO打破了connect-auth非常强大且易于阅读的洋葱环架构。不去——我的观点:)。 你可以在这里找到一篇关于connect如何工作和洋葱圈想法的非常好的简短文章。 如果你——如前所述——只是想使用数据库或文件的基本或http登录。Connect-auth太大了。它更适合OAuth 1.0、OAuth 2.0等


使用connect进行非常简单的身份验证

(这是完整的。只是执行测试,但如果你想在生产中使用它,请确保使用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);

NOTE

我在一年多前写了这个声明,目前没有活动节点项目。可能会有API-Changes in Express。如果我需要修改什么,请加上评论。