Node.js用の既存のユーザー認証ライブラリはありますか?特に、ユーザーのパスワード認証を実行して(カスタムバックエンド認証DBを使用)、そのユーザーをセッションに関連付けることができるものを探しています。
Authライブラリを作成する前に、人々が既存のライブラリを知っているかどうかを確認しました。グーグル検索で明らかなものを見つけることができませんでした。
-シュレヤス
接続ミドルウェアへのconnect-authプラグインはまさに私が必要なもののように見えます: http://wiki.github.com/ciaranj/connect-auth/creating-a-form-based-strategy
Express [ http://expressjs.com ]を使用しているので、connectプラグインは非常にうまく適合します。これは、expressがconnect
ConnectまたはExpressの認証フレームワークを探している場合、Passportは調査する価値があります。 https://github.com/jaredhanson/passport
(開示:私はパスポートの開発者です)
Connect-authとeveryauthの両方を調査した後、Passportを開発しました。どちらも素晴らしいモジュールですが、私のニーズには合いませんでした。もっと軽くて目立たないものが欲しかった。
Passportは個別のモジュールに分割されているため、必要なもののみを使用することを選択できます(OAuth、必要な場合のみ)。また、Passportはアプリケーションにルートをマウントしないため、認証をいつどこで行うかを柔軟に決定でき、認証が成功または失敗したときに何が起こるかを制御するフックがあります。
たとえば、フォームベース(ユーザー名とパスワード)認証をセットアップする2段階のプロセスを次に示します。
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などを介した認証には、追加の戦略を利用できます。必要に応じて、カスタム戦略をプラグインできます。
多くの優れたライブラリを見つけられなかったのは、認証にライブラリを使用することのほとんどが過剰に設計されているためだと思います。
あなたが探しているのは単にセッションバインダーです:)とのセッション:
if login and user == xxx and pwd == xxx
then store an authenticated=true into the session
if logout destroy session
それでおしまい。
connect も使用していますが、次の2つの理由でconnect-authを使用していません。
私見は、コネクトの非常に強力で読みやすいオニオンリングアーキテクチャであるコネクト認証を破ります。ノーゴー-私の意見:)。 connectの仕組みとオニオンリングのアイデアに関する非常に優れた短い記事を見つけることができます here 。
書かれているように、データベースまたはファイルで基本ログインまたはhttpログインを使用する場合。 Connect-authが大きすぎます。 OAuth 1.0、OAuth 2.0&Coのようなものに向いています
(完了です。テストのために実行するだけですが、実稼働環境で使用する場合は、必ずhttpsを使用してください)状態を変更する:)
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);
私は1年以上前にこの声明を書きましたが、現在アクティブなノードプロジェクトはありません。そのため、ExpressにはAPIが変更される可能性があります。何か変更する必要がある場合は、コメントを追加してください。
私は基本的に同じものを探していました。具体的には、次のものが必要でした。
私がやったことは、認証したい各ルートに引数として渡すミドルウェア関数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("/");
}
});
});
とにかく、このアプローチは主に柔軟でシンプルになるように設計されました。私はそれを改善する多くの方法があると確信しています。もしあれば、あなたのフィードバックがとても欲しいです。
編集:これは簡単な例です。実稼働システムでは、パスワードをプレーンテキストで保存および比較する必要はありません。コメント者が指摘しているように、パスワードセキュリティの管理に役立つライブラリがあります。
サードパーティ/ソーシャルネットワークログインの統合が必要な場合は、 everyauth もご覧ください。
これが私のプロジェクトの1つからの基本認証のコードです。 CouchDBと追加の認証データキャッシュに対して使用しますが、そのコードを削除しました。
リクエスト処理を認証方法でラップし、認証が失敗した場合の2番目のコールバックを提供します。成功コールバックは、追加のパラメーターとしてユーザー名を取得します。失敗コールバックで、間違った資格情報または欠落している資格情報を持つ要求を正しく処理することを忘れないでください。
/**
* 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;
}
};
別の認証方法は、パスワードの固有の問題を回避するエクスプレス用の トークンベースの認証 モジュールであるPasswordlessです[1]。実装は高速で、多くのフォームを必要とせず、平均的なユーザーにより優れたセキュリティを提供します(完全な開示:私は著者です)。
[1]: パスワードは廃止されました
数年が経ち、Expressの認証ソリューションを紹介したいと思います。 Lockitと呼ばれます。プロジェクトは GitHub にあり、短いイントロは my blog にあります。
では、既存のソリューションとの違いは何ですか?
require('lockit')
、lockit(app)
、完了username
およびpassword
のみ。examples を見てください。
以下に、ノードjs認証用の2つの一般的なGithubライブラリを示します。
Drywall と呼ばれるプロジェクトがあり、これは Passport でユーザーログインシステムを実装し、ユーザー管理管理パネルもあります。 Djangoのようなものに似た、Node.js向けの完全な機能を備えたユーザー認証および管理システムを探しているなら、これがそれです。ユーザー認証および管理システムを必要とするノードアプリを構築するための非常に良い出発点であることがわかりました。 Passportの仕組みについては、 Jared Hansonの回答 を参照してください。
Angularクライアントのユーザー認証を提供するAPIのmongoを使用した簡単な簡単な例
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);
}
}
});
});
};
次に、認証が必要なルートで、ユーザーセッションを確認するだけです。
if (!req.session.user) {
res.send(403);
}
これは、タイムスタンプ付きトークンを使用する新しい認証ライブラリです。トークンは、データベースに保存することなく、ユーザーにメールまたはテキストで送信できます。パスワードレス認証または2要素認証に使用できます。
https://github.com/vote539/easy-no-password
開示:私はこのライブラリの開発者です。