web-dev-qa-db-ja.com

node.jsおよびexpress.jsでのグループ/ルールベースの承認アプローチ

Express.jsでのロールベースの承認に適した戦略は何ですか?特にエクスプレスリソースとは?

Express-resource の場合、ハンドラーがないため、3つのオプションがあると思います。

  1. ミドルウェアを使用する
  2. 認可関数をリソースに渡し、各リソース要求を個別にチェックします
  3. 認証直後にすべてのリクエストで承認を確認する

他の解決策はありますか?

グループ/ロールベースの認証は、かなり古いアプローチです。アクセス制御の新しい方法はありますか?そうでない場合、役割ベースの承認をnode.jsにどのように適用できますか? (NoSQL/CouchDB/Redisを使用して)グループとルールの関係をどこに保存しますか?

例として、構造:

/
  /forums
    /forums/threads

インデックス付きの各リソース、新規、作成、表示、編集、更新、破棄。スレッドやフォーラムなどを編集/削除できる人もいれば、そうでない人もいます。

21
Patrick

Connect-roles は非常にシンプルで、ドキュメントも非常に明確です。

var user = roles;

app.get('/profile/:id', user.can('edit profile'), function (req, res) {
  req.render('profile-edit', { id: req.params.id }); 
})
app.get('/admin', user.is('admin'), function (req, res) {
  res.render('admin');
}
12
xinbenlv

ルート固有のミドルウェアが(少なくともクリーンな方法で)許可されていないため、express-resourceを使用してクリーンな方法でこれを解決するのは難しいと思います。

私はExpress-Resourceモジュールと同様のレイアウトを選択しますが、それをプレーンな古いExpressでルーティングします。このようなもの:

// Resource
var forum = {
  index: // ...
  show: // ...
  create: // ...
  update: // ...
  destroy: // ...
};

// Middleware
var requireRole = function(role) {
  return function(req, res, next) {
    if('user' in req.session && req.session.user.role === role)
      next();
    else
      res.send(403);
  }
};

// Routing
app.get('/forums', forum.index);
app.get('/forums/:id', forum.show);
app.post('/forums', requireRole('moderator'), forum.create); // Only moderators can create forums
app.delete('/forums/:id', requireRole('admin'), forum.destroy); // Only admins can delete forums

UPDATE:express-resource内のルート固有のミドルウェア、たとえば ここ 。一般的なビューは、アクションごとに配列を持っているようです、例えば:

var forums = {
  index: [ requireRole('foo'), function(req, res, next) { ... } ]
};

プルリクエストを調べて、使用できるものがあるかどうかを確認できます。もちろん、それが気に入らなければ、私はそれを完全に理解しています。将来的にはExpress-Resourceでこのようなものが表示されると確信しています。

私が考えることができる他の唯一の解決策は、Jan Jongboomの回答に沿ったものです。これは、リソースをexpress-resourceでマウントしますが、ミドルウェアをその「外部」に接続します。

app.delete('*', requireRole('admin')); // Only admins are allowed to delete anything
app.put('/forums/*', requireRole('moderator')); // Only moderators are allowed to update forums

しかし、私はこれがURLをあちこちに漏らしていることを後悔しています。

私は同じ質問を調査していて、いくつかの良いモジュールに出くわしました。ここにあるnode-aclパッケージに焦点を当てています。 https://github.com/optimalbits/node_acl

このパッケージはACLパターンを非常に理解しやすい方法で実装しているようで、ノード/エクスプレスアプリケーションに簡単に統合する方法を提供しています。

まず、リソース、ロール、および権限を定義する必要があります。

たとえば、リソースは次のようになります。

/
  /forums
    /forums/threads

役割は

public
admin
user
   john
   jane

この例では、johnとjaneの役割は実際のユーザーアカウントにマッピングできますが、ユーザー役割のすべての権限を継承します。

リソースに対する権限

  • つくる
  • 公演
  • 更新
  • 破壊

または、標準のCRUD操作。

それらが定義されたので、node-aclを使用してaclを設定する方法を見てみましょう。これらのメモはドキュメントから派生しています

パッケージをインポートする

var acl = require('acl');

バックエンドを設定します。私のアプリはmongodbを使用していますが、node-aclパッケージは他のストレージメカニズムをサポートしています

acl = new acl(new acl.mongodbBackend(dbInstance, prefix));

私のアプリはmongooseを使用しているため、dbInstanceはmongoose.connection.dbに置き換えられます

次に、ACLにロールを追加します。 node-aclでは、ロールに権限を付与することで作成されます。 1つの石で2羽の鳥を殺すようなものです(鳥は実際には害されていません)。

acl.allow('admin', ['/', '/forum', '/forum/threads'], '*');
acl.allow('public', ['/', '/forum', '/forum/threads'], 'show');
acl.allow('user', ['/', '/forum', '/forum/threads'], ['create', 'show']);

新しいリソースがジョンによって作成されたと想定して、ジョンがそのリソースを更新および削除できるようにする新しいレコードを追加します。

acl.allow('john', ['/forum/threads/abc123'], ['update', 'delete']);

私のアプリケーションもExpressを使用しているため、ルーティングミドルウェアアプローチを使用してルートをチェックします。私のルーティング構成では、次の行を追加します

ほとんどの高速構成では、これはposのように見えます

app.post('/', acl.middleware(), function(req, res, next) {...});
app.post('/forums', acl.middleware(), function(req, res, next) {...});
app.post('/forums/:forumId', acl.middleware(), function(req, res, next) {...});
app.post('/forums/threads', acl.middleware(), function(req, res, next) {...});
app.post('/forums/threads/:threadId', acl.middleware(), function(req, res, next) {...});

パラメータが渡されない場合、req.userIdで定義されたロールが、ルートではなく識別されたリソースでhttpメソッドを実行できるかどうかがチェックされます。

この例では、httpメソッドはpostですが、構成で識別される各httpに対して同じことを行います。

これは、以前に定義された許可についての質問を提起します。これらの質問に答えるには、権限を

  • つくる
  • 公演
  • 更新
  • 破壊

従来に

  • 役職
  • get
  • 置く
  • 削除する

この例ではすべてハードコードされていますが、コードを変更することなく動的に作成、読み取り、更新、削除できるように、アクセス許可の管理インターフェイスを用意することをお勧めします。

私はnode-aclプラグインアプローチが好きです。非常に単純で柔軟なAPIを使用して、非常にきめ細かい権限とロールの割り当てを可能にするからです。彼らのドキュメンテーションにはもっとたくさんあります、私の例は私がパッケージを持っていた場合を示しています。

うまくいけば、これが役立ちます。

27
Isioma Nnodum

Expressでは、すべての演算子にフックするハンドラー(http://expressjs.com/guide.html#passing-routeコントロール)を追加できます。ここで、前提条件の検証を行うことができます。ここでは、ユーザーのロールを取得し、HTTP動詞(PUT、DELETEなど)またはURL(param('op')は「編集」など)に基づいてアクセスを制限できます。

app.all('/user/:id/:op?', function(req, res, next){
  req.user = users[req.params.id];
  if (req.user) {
    next();
  } else {
    next(new Error('cannot find user ' + req.params.id));
  }
});
3
Jan Jongboom

非明示的なルーティングミドルウェアとしてモジュールを作成しました。高速ルートでうまく機能します。

GitHubのガンダルフ

2
Patrick

あなたはCasbinを試すことができます: https://casbin.org/ 、それはNode.jsバージョンを持っています。また、express-authzというExpress.jsミドルウェアもあります。 https://casbin.org/docs/en/middlewares

0
Yang Luo