役割ベースのREST API?


27

異なるロールを持つ複数のユーザーが含まれるリソースにアクセスできるREST APIを構築しています。

スコープをシンプルに保つために、「student / teacher / class」ドメインを取り上げます。

GET /students アクセスするリソースです。

ユーザーには、学生や教師などの役割がある場合があります

生徒はクラスの生徒にのみアクセスできます。教師は、教えるクラスの生徒にアクセスできます。いくつかの用途は学生であり、他のクラスも教えます。彼らは彼らのクラスの生徒と彼らが教えるクラスの生徒にアクセスできなければなりません。

理想的には、これを2つの機能として実装します。ロールごとに1つ、ユーザーが複数のロールを持つ場合は「結合」します。

私の質問は、これを実装するためにどのパターンを使用すればよいですか?

外部的に

  • ロールごとにAPIを分割する必要がありますか?GET /teacher/studentsそしてGET /student/studentsそれは右の私には思われません。
  • すべてを維持する私は1つのリソースです(推奨)

内部的に

内部的にどのように実装する必要がありますか?

  • すべての方法は、BIGスイッチで開始する必要がありますか、役割ごとに行う必要がありますか
  • 役割ごとにリポジトリを実装する必要がありますか?
  • これを達成するのに役立つ設計パターンはありますか?

副次的なコメントとして:私はASP.NET Web APIEntity Framework 6を使用していますが、概念的な実装には関係ありません。


3
「これは素晴らしい質問です。似たようなことをしようとしているので、その解決策があったかどうか知りたいです。まず、必要なデータをすべて返すAPIを実装します。 、各クライアントはAPIに直接接続するのではなく、そのユーザーからのロールに応じてデータをフィルター処理するプロキシに接続します」
-Cleiton

回答:


11

ロールではなく、リソースを中心にAPIを設計する必要があります。例:

/rest/students

学生を見ることができる役割を持つ人なら誰でもアクセスできるようにする必要があります。

内部的には、ロールベースのセキュリティを実装しています。その方法はアプリケーションの詳細によって異なりますが、ロールテーブルがあり、各ユーザーが1つ以上のロールを持ち、それらのロールが各ユーザーがアクセスできるものを決定するとします。学生にアクセスするためのルールはすでに述べています。

  • 学生は受講するクラスの学生にアクセスできます
  • 教師は教えるクラスの生徒にアクセスできます

だから人が電話したとき:

/rest/students

学生にアクセスするメソッドを呼び出し、その人の役割を渡します。疑似コードは次のとおりです。

roles = person.roles; //array
students = getStudents( roles );
return students;

そして、その方法では、例えば次のように別々の呼び出しで各役割の生徒を取得できます。

factory = getFactory();
classes= [];
students = [];
for( role in roles ){
    service = factory.getService( role );
    // implementation details of how you get classes for student/teacher are hidden in the service
    classes = classes.merge( service.getClasses( person ) );
    // classes[] has class.students[]
    // loop on classes and add each student to students, or send back classes with nested students? depends on use case
  }
}

それはあなたができることの非常に大まかなアイデアであり、必ずしもあなたの特定のニーズに合うとは限りませんが、それはあなたに関係する部分の感覚を与えるはずです。リストされた各学生とクラスを返したい場合、これは良いアプローチです。生徒だけが必要な場合は、各クラスから生徒を抽出して、生徒のコレクションにマージできます。

いいえ、役割ごとに個別のリポジトリを用意するべきではありません。役割は、データの取得方法と、おそらくデータを使用して何ができるかを決定することです(たとえば、教師は生徒の成績を入力できます)。データ自体は同じです。

パターンに関しては、このアプローチはファクトリパターンを使用して、ロールに基づいてデータを取得するサービスを抽象化します。役割ごとに別々のサービスを用意することが適切な場合とそうでない場合があります。プログラムの各段階でコードの量を最小限に抑え、スイッチやifブロックよりも読みやすくするため、このアプローチが気に入っています。


1
返信いただきありがとうございます。私はあなたが提案したようなことをすることになりました。LINQ2SQL(C#)を使用すると、クエリを各「ロール」に渡し、ユーザーが取得した各ロールの場所を適用できます。結果は、ユーザーがアクセスできる各ロールの「OR」条件を持つsqlステートメントになります。ユーザーにロールが割り当てられていない場合、呼び出し元であるEnumarable.Empty()を返すだけです。
キャスパージェンセン

0

ペンと紙を見つけて、システムのモデリングを開始します。

おそらくPERSONというドメインエンティティが必要であることがわかります。STUDENTSとTEACHERの両方が "is-a" PERSONであるため、firstname、lastnameなどの一般的な属性を持つPERSONという抽象エンティティを作成できます。TEACHER-> is-a-> Person。これで、生徒に適用されない教師の特性を見つけようとすることができます。例:教師は、1つまたは複数の主題に関するクラスを教えます。

セキュリティの実施は、アプリケーションの非機能的な側面と見なされます。これは横断的な懸念事項であり、「ビジネスロジック」の外部で処理する必要があります。@Robert Munnが指摘しているように、ROLEはすべて1か所で管理する必要があります。役割を使用して特定の機能へのアクセスを制限するのはかなり粗く、概念は役割ベースのアクセス制御(RBAC)と呼ばれます

教師が学生の成績を見ることができるかどうかを確認するには、ドメインモデルで表現する必要があります。教師が主題のプログラミングのクラスを持っているとしましょう。モデルでは、生徒がさまざまな科目のクラスに参加することをおそらく表現します。これは、アプリケーション/ビジネスロジックが起動する場所です。これは、テスト駆動開発を使用して確認できるロジックです。

アプリケーションをテスト可能かつモジュール化するには、リソースを分割する必要があります。

とにかく、実際に私が意味することを示す最良の方法は、コードで表示することです:) GitHubのページはこちらです:https : //github.com/thomasandersen77/role-based-rest-api

がんばろう :)


3
あなたのリンクは消えました
...-クレイトン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.