web-dev-qa-db-ja.com

Express REST APIでロールと権限を実装する最良の方法は何ですか

Express jsで役割と権限を実装するには、専門家の意見が必要です。 Express jsを使用してRestful Apiを開発する予定ですが、認証と承認に利用できるオプションがたくさんありますが、ロールと権限を実装するのに十分な情報を取得できませんでした。

17
zahid rasool

テーブルの作成

最初に、ロール、権限、およびリソース間の関連付けを保持するテーブルを作成する必要があります。

  1. ロールテーブルを作成します(「管理者」、「ユーザー」、「ゲスト」)
  2. リソーステーブル(「ユーザー」、「プロジェクト」、「プログラム」)を作成する
  3. 許可テーブルを作成します(「作成」、「読み取り」、「書き込み」、「削除」、「拒否」)
  4. 3つのテーブルすべてをソースとしてジャンクションテーブルを作成する

権限テーブルにはそのような粒度は必要ないかもしれませんが、それを好む人もいます。たとえば、Read!= trueをチェックするだけなので、実際に 'Deny'は必要ありません。

リソースのロールのパーミッションが必要な場合は、role_idとresource_idを調べて、どのパーミッションがtrueに設定されているかを確認するだけです。

ミドルウェアの作成

Expressを使用しているため、ミドルウェアを簡単に追加できます。たとえば、usersというルーターがあるとします。

users.post('/', getAuth, handleUserPost)

投稿を行っているユーザーを識別するリクエストに何らかのトークンがあり、ユーザーオブジェクトをリクエストオブジェクトにアタッチしていると仮定すると、これを行うことができます。

getAuth = function (req, res, next) {
  if(req.user) { 
    db.getPerms({role_id: req.user.role_id, resource_id: req.resource.id})
       .then(function(perms){
          var allow = false;
          //you can do this mapping of methods to permissions before the db call and just get the specific permission you want. 
          perms.forEach(function(perm){
              if (req.method == "POST" && perms.create) allow = true;
              else if (req.method == "GET" && perms.read) allow = true;
              else if (req.method == "PUT" && perms.write) allow = true;
              else if (req.method == "DELETE" && perm.delete) allow = true;

          })
          if (allow) next();
          else res.status(403).send({error: 'access denied'});
       })//handle your reject and catch here
   } else res.status(400).send({error: 'invalid token'})
}

このコードはこの例のためだけに荒削りにされているので、コピーして貼り付けることはしませんが、正しいアイデアを提供するはずです。

20
Dave Briand

Node.jsのロールの権利


パート1:役割と権利とは?

役割の権利の実装は、ソフトウェアの重要な部分です。役割は責任の位置であり、すべての責任は与えられたいくつかの権利を享受します。いくつかの役割の間には共通の権利があり、特定の役割に厳密に属する権利があります。

権限とは、ロールがアクセスすることを許可されていることです。したがって、ロールの権限の情報を格納するコレクションをデータベースに作成する必要があります。ロールコレクションスキーマは

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const RoleSchema = new Schema({
roleId:{
type:String,
unique:true,
required:[true,"Role Id required"]
},
type:{
type:String,
unique:true,
required:[true,"Role type is required"]
},
rights:[{
name: String,
path: String,
url: String
}]
});
module.exports = Role = mongoose.model('role',RoleSchema);

ここで、存在すると思われるすべてのロールがロールコレクションにあり、上記のスキーマタイプであることに注意してください。

オブジェクトのスキーマ権限配列には、オブジェクトにキーがあることがわかります。

  • name(「set-username」のようなURLの名前)
  • パス(ベースパスヒット "/ users /")
  • rl(リクエストされたURLまたは完全なパス "/ users/set-username")

したがって、ロールuserを持つユーザーがユーザー名を変更する権限を持っている場合、URL /users/set-username。ただし、放浪者はこのurlにアクセスできません。adminやsuperadminのような上位のロールは、論理的にすべての下位のロール権限(url)にアクセスできる必要があります。

実際のアプリケーションでの役割は次のとおりです。

  1. 放浪者私たちのサイトを訪問している人。すべてのパブリックルートにアクセスできるはずです。すべての人がアクセスできるシンプルなURL /パブリックURLです。認証された権利ではありません
  2. ゲスト登録されているが確認されていない人は、メールが確認されていないと言います)。
  3. ユーザー確認済みメールを持っている人
  4. 管理者確認後にSuperAdminによって管理者を作成しました。彼はほとんどの権利を享受しています
  5. スーパー管理者アプリケーションのマスター。彼はいくつかのより洗練された権利を享受します。管理者よりも多くの権利

今まで、私たちは何が正しく正しいのか、そしてそれがどのように役割にマッピングされるのかを理解しました。


パート1.5:登録済みURL /構成URL

次のようなregisteredUrls.jsというファイルがあります。

module.exports = {
    simple:{
        "/":[""],
        '/users/':["login","register"],
    },
    auth:{
        //admin
        '/admin/': ['load-users' , 'set-new-password','delete-user'],
        '/teacher/':["add-teacher","delete-teacher","edit-teacher"],
        '/student/':["add-student","delete-student","edit-student","test-result"],

        //user
        '/test/':["view-test","submit-test"],
        '/profile/': ['change-username', 'update-profile-data',  'set-new-password', 'upload-pic', 'update-social-links'],
        '/teacher/':['load-teacher'],
        '/student/':['load-student']

    }
}

同様にconfgUrls.js

const configUrls= {
    '/roles/': ['get-rights', 'create', 'update-rights', 'load', 'delete', 'assign']
}
module.exports = configUrls;

パート2:SuperAdminの作成

これは、アプリケーションの最も重要な部分です。サーバーが初めて起動するとき、または再起動/再起動するたびに、この手順が実行されます。config/ init.jsで手順に従います。

  1. すべての単純なURL(パブリック)と認証URL(管理者とユーザー)およびスーパー管理者固有のURLをsuperAdminRights []にロードします。
  2. 次に、存在しない場合は、関数superadminを使用してユーザーを作成する関数を実行します。
  3. タイプが「スーパー管理者」のロールが見つかった場合は、その権限を新しい権限(superAdminRights)に置き換えます。else:createタイプが「スーパー管理者」のロールを作成し、その権限を満たします(superAdminRights)。

この関数呼び出しの終わりに、アプリケーションにすべての洗練されたURL /権限が初期化されたスーパー管理者がいることを常に確認します。


パート3:スーパー管理者固有のURL

これらは、スーパー管理者のみが享受する権利であり、登録済みのurlファイルと並行して個別のファイルで維持する必要があります。これらには、スーパー管理者のみが使用するルートをマップするurl権利が含まれます。ここには、ロールを作成し、ロールをロードし、ロールIDの権限を取得し、ロールID /ロールタイプの権限を更新し、ユーザーにロールを割り当て、ロールを削除するためのルートがあります。

コード内の各ユーザーについて、ロールをゲストからユーザーに変更する必要があります(電子メールの確認後など)。または、ゲスト/ユーザーは、assign-role urlを使用してsuperadminによって管理者に変更します。次に、ルート更新権を使用して管理者権限を更新します。

このプロセスは、すべての役割がコレクション文書を持ち、そこに権利が満たされていることを確認します。


パート4:認証ミドルウェア

[〜#〜] rbacs [〜#〜] logicの中心です。ここでは、プロセスに従うミドルウェアを使用します。

1. [AUTH_URLS]のすべての認証に必要なURLをauth-urls(registeredUrls.js)とsuper-admin-specific-urls(confgUrls.js)および異なる[SIMPLE_URLS]の単純なURLで埋めます。

2.次に、(AUTH_URLS.indexOf(request.url)> -1){3rd step} if if(SIMPLE_URLS.indexOf(request.url)>-1){then public url so simple allow next ()} else {response unknown url}

3.このステップでは、AUTH_URLSで要求されているurlが見つかった場合、認証トークンヘッダーのトークンチェックが必要であり、それからトークンを抽出することが必要であることがわかります。 「。

4.トークンが見つかりました。このトークンに有効なセッションがあることを確認します。{5th step}の場合、トークンセッションが再度見つかりません。 5. jwtトークンを検証します。検証された場合は検証します{6.step}、そうでない場合は「無効なjwtトークン」と応答します。

6.現在は正しいURLが要求され、トークンセッションが存在し、jwt有効なトークンがあります。セッションからのロールタイプ情報を使用して(セッションに保存されているのはユーザーとトークンの基本情報です)、このユーザーセッションのロールタイプのロールを検索しますrequest.urlがrights []。ifに含まれているかどうかを確認します。{7th step} else {reponse "role not found/unknown user"}}。

7.見つかった場合{このURL next()へのアクセス権がある} else {response "access denided"}

3
Aniket Jha