質問

実際の組織のメンバー向けに、Railsでコミュニティベースのサイトを構築しています。 RESTful設計のベストプラクティスを順守しようとしていますが、そのほとんどは多かれ少なかれ本書です。私の脳をきちんとしたRESTfulサークルで実行している問題は、許可の問題です。 認証は、広く受け入れられているRESTfulソリューションを使用した簡単で長期にわたる問題ですが、RESTful認証は少し難解なようです。リソースへのアクセスを制御するための最も一般的で柔軟なフレームワークを提供し、可能な限りシンプルでありながら、RESTfulアーキテクチャに準拠するアプローチを見つけようとしています。 (また、ポニー。)

考慮事項:

  1. ユーザー、ページ、投稿など、さまざまなリソースへのアクセスを制御する必要があります。
  2. 特定のリソースの承認は、単純なCRUDよりもきめ細かくする必要があります。
  3. 自分や他のユーザーがアプリケーション内から承認ルールを編集できるようにします。
  4. 承認ルールは、(概念的に)Owner(User、Resource)やLocked(Topic)などの述語に依存することを許可する必要があります

考慮事項(2)は、私に最も関係するものです。許可の概念とアクションのRESTfulの概念の間には、インピーダンスの不一致があるようです。たとえば、(掲示板のように)投稿します。 RESTは、Postリソースに対する4つの操作、Create、Read、Update、およびDeleteの存在を指示します。ユーザーが自分の投稿を更新できるようにする必要があると言うのは簡単ですが、特定のユーザー(またはロール、グループ)のみがそれらのロックを許可する必要があります。ロックを表す従来の方法は投稿の状態内にありますが、同じ条件の下でユーザーが提供する(完全に有効な)値に応じて投稿を更新できる場合とできない場合があります。投稿の状態を変更するための実際には2つの異なるアクションがあり、それらを単純化することは、RESTful原則の違反を偽装することだけであることは明らかです。

(この問題は、無効または一貫性のないデータのために更新が失敗する問題とはまったく異なることに注意してください—非特権ユーザーからのロック要求は、原則として非常に有効です、単に許可されていません。)

  

腐敗の別の単語ではありませんか?

これは、投稿を分解することで克服できます。ロックは特定の投稿のサブリソースであり、作成または破棄するために別のアクセス許可を設定できます。このソリューションにはRESTのリングがありますが、理論的および実用的な困難をもたらします。ロックを除外する場合、他の属性はどうですか?気まぐれに、管理者のメンバーだけに投稿のタイトルの変更を許可する必要があると判断したとしますか?承認の簡単な変更には、それに対応するためにデータベースの再構築が必要になります!これはあまり解決策ではありません。分解の戦略の下でこの種の柔軟性を可能にするには、すべての属性がリソースである必要があります。これはちょっとしたジレンマをもたらします。私の暗黙の前提は、リソースがデータベース内で表として表されることです。この仮定の下では、すべての属性のリソースとは、すべての属性のテーブルを意味します。明らかに、これは実用的ではありません。ただし、この仮定を削除すると、テーブルとリソース間のインピーダンスの不一致が生じ、ワームの缶が開かれる可能性があります。このアプローチを使用するには、これまでに説明したよりもはるかに詳細な検討が必要です。一つには、ユーザーは複数の属性を一度に編集できることを合理的に期待しています。リクエストはどこに行きますか?すべての属性を含む最小のリソースに?個々のリソースに並行して?月へ?

  

これらのものの中には、他のものとは異なるものがあります…

で分解しないと仮定します賛辞。その場合の代替策は、各リソースの特権セットを定義することです。ただし、この時点で、RESTの均一性は失われます。リソースのアクセスルールを定義するには、システムがそのリソースの機能に関する特定の知識を持っている必要があります。さらに、子リソースに同じ名前の特権があったとしても、子孫リソースにパーミッションを一般的に伝播することは不可能になりました。特権間に固有の意味的なつながりはありません。 RESTのような標準特権のセットを定義することは、両方の世界で最悪のように思えるので、リソースの種類ごとに個別のアクセス許可階層に縛られています。

  

まあ、鼻をしました。そして帽子。しかし、それはリソースです!

上記のアプローチの欠点のいくつかを軽減することを私が見た提案の1つは、 resources で作成/削除、 attributes で読み取り/書き込みとして許可を定義することです。このシステムは、リソースとしての属性とリソースごとの特権の間の妥協です。CRUDのみが残っていますが、認証の目的のために、読み取りと更新は属性に関連します。これは擬似リソースと考えることができます。これは、属性としての属性アプローチの実用的な利点の多くを提供しますが、概念的な整合性はある程度まで損なわれます。アクセス許可は、リソースからリソースへ、およびリソースから擬似リソースへと伝搬できますが、擬似リソースからは伝搬できません。私はこの戦略の影響を完全には調査していませんが、有望かもしれません。そのようなシステムは、モデルの不可欠な部分として最適に機能すると思います。たとえば、Railsでは、 ActiveRecord を後付けすることができます。これは私にとってかなり抜本的なように思えますが、承認は根本的な横断的関心事であり、正当化される可能性があります。

  

ああ、ポニーを忘れないでください

これらはすべて、述語権限の問題を無視します。明らかに、ユーザーは自分の投稿を編集できるはずですが、他のユーザーは編集できません。同様に、管理者が作成した権限テーブルには、ユーザーごとに個別のレコードを含めることはできません。これはめったにない要件ではありません—トリックはそれを汎用にすることです。必要な機能はすべて rules を述語化するだけで得られるので、ルールの適用可能性を迅速かつ迅速に決定できると思います。ルール" 作成者(ユーザー、投稿)"すべてのユーザーに対して" に変換し、Author(User、Post)などの投稿、ユーザーによる投稿の書き込みを許可"、" すべての投稿のロック(投稿)を拒否 " " Locked(Post)などのすべての投稿に対して、すべての投稿の書き込みを拒否" (そのようなすべての述語を1人のユーザーと1つのリソースの観点から表現できれば、 grand になります。)概念的に結果の「最終」は、ルールは非予測的です。これは、そのようなシステムを実装する方法の問題を提起します。述語はModelクラスのメンバーである必要がありますが、ルールのコンテキストでどのように優雅にそれらを参照できるのかわかりません。これを安全に行うには、何らかのリフレクションが必要になります。ここでも、これにはモデルの実装の改良が必要だと感じています。

  

どのようにもう一度スペルしますか?

最後の質問は、これらの認可ルールをデータとして最適に表現する方法です。データベーステーブルは、allow / denyおよびC / R / U / D(またはCRUD bits?または{C、R、U、D}× {allow、deny、inherit }?)、およびパスを含むリソース列。おそらく、便宜上、「継承」ビット。述語に関しては途方に暮れています。別のテーブル?確かに多くのキャッシングが tであることを防ぎます

役に立ちましたか?

解決

申し訳ありませんが、この質問を正義にする時間はありませんが、SOについてよく考えられた質問を見るのは素晴らしいことです。 コメントを次に示します。

HTTP動詞をCRUDにマッピングするというtrapに陥らないでください。はい、GETとDELETEはかなりきれいにマップしますが、PUTはCreateとUpdateを実行できます(ただし、完全な置換のみ)。POSTはワイルドカード動詞です。 POSTは、GET、PUTおよび 削除。

属性を使用してオブジェクトのステータスを表すことは、状態管理に対する1つのアプローチにすぎません。次のリクエストが何をするか想像できると思います:

POST /LockedPosts?url=/Post/2010

サブリソースは、リソースの現在の状態を管理するための有効なアプローチでもあります。リソースの「状態」を処理する義務を感じません。属性とその「データ」一貫した方法で属性。

リソースをテーブルに直接マップしようとすると、深刻な制約を受けます。 RESTの制約に従うと、使用可能な動詞が突然非常に制限されることを忘れないでください。使用するリソースで創造的になることで、それを補う必要があります。 1つのリソースに自分を1つのテーブルに制限すると、エンドアプリケーションの機能が大幅に制限されます。

Rails、ASP.NET MVC、WCF Restのユーザーが、RESTの制約内で特定のことをどのように行うかについてStackOverflowで質問を投稿しているのを定期的に確認しています。多くの場合、問題はRESTの制約ではなく、RESTfulアプリケーションのサポートにおけるフレームワークの制限にあります。最初に問題に対するRESTfulなソリューションを見つけてから、それが選択したフレームワークにマッピングできるかどうかを確認することが不可欠だと思います。

リソース自体よりも細かい粒度で存在する権限モデルを作成する限り。 RESTの主要な制約の1つはハイパーメディアであることを忘れないでください。ハイパーメディアは、関連するエンティティを見つけるだけでなく、有効/許可された状態遷移を表すためにも使用できます。条件に基づいて権限に基づいて埋め込まれたリンクを含む表現を返す場合、誰が実行できるアクションを制御できます。つまり、ユーザーがPOST 342のロックを解除する権限を持っている場合、表現に埋め込まれた次のリンクを返すことができます。

<Link href="/UnlockedPosts?url=/Post/342" method="POST"/>

彼らがその許可を持っていない場合、リンクを返さないでください。

ここでのあなたの難しさの一つは、あなたが一度に大きすぎる問題をかみ込もうとしていることだと思います。ドメインモデルで承認を管理するために、アクセス許可と述語を管理する方法とは異なる問題として、クライアントに公開しようとしているRESTfulインターフェイスを見る必要があると思います。

私はあなたの質問のいずれにも直接答えていないことを理解していますが、何らかの形で役立つ可能性のある視点を提供したことを願っています。

他のヒント

最近、私の懸念のほとんどに対処していると思われる認証ソリューションを発見しました。この質問をお気に入りに追加した場合、興味があるかもしれません:

https://github.com/stffn/declarative_authorization

Darrelが指摘したように、RESTはCRUDではありません。識別されたリソースが粗すぎて均一なインターフェースでは十分な制御ができない場合、リソースをサブリソースに分割し、元のリソースをコンポーネントへのハイパーリンクの「コレクション」として使用します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top