アクセス制御の標準的な手法(設計パターン)


9

私は自分のインターフェース設計を見ていて、がアクセスしたいuserとを与えられた場合に、ロールベースのアクセス制御を実装するための最も「正しい」方法を決定するのに苦労しています。subjectuser


私が見る限り、3つのコアオプションがあります(4番目は最初の3つの粗野化、5番目は4番目の微調整です)。

  1. subject持つ権限のリストを使用してをクエリしuserます-subject.allowAccess(user.getPermissionSet)
  2. に必要なuser権限のリストを使用してをクエリしsubjectます-user.hasPermissionTo(subject.getRequiredPermissions())
  3. サードパーティにクエリを実行して、権限の共通部分を見つけます- accessController.doPermissionSetsIntersect(subject.permissionSet, user.getPermissionSet())
  4. subject/のいずれかを照会しuser、「決定」をサードパーティのクラスに委任する
  5. 持ってuserアクセスしようとするとsubjectアクセスが許可されていない場合は、エラーをスローします

私はオプション4に傾いています- フィールドに操作を委託するための呼び出しをsubject含めるaccessControllerフィールドがありますsubject.userMayAccess(User user)

class Subject {
    public function display(user) {
        if(!accessController.doPermissionSetsIntersect(this.permissionSet, user.getPermissionSet())) {
            display403(); //Or other.. eg, throw an error..
        }
    }
}

..しかし、これはさらに質問を引き起こします:

  • accessControllerフィールド対静的クラスである必要があります。
  • 必要がありますsubject 知っている必要とされるどのような権限は、それを表示することができますか?
  • 召喚に関して、知識の最小の原則はここでsubject.display()どこに作用しますか?呼び出し元はsubject.display()、アクセス制御が有効であることを知っている必要がありますか?(subject.display()最終的な「テンプレートメソッド」はどこにあるか)
  • subject.display()アクセス制御を管理し、ユーザーが必要な権限を持っていない場合に例外をスローしますか?

この状況で何が「ベストプラクティス」と見なされますか?チェックを実行する責任は実際にどこで発生しますか?

これはどちらかと言えば実装に進む学術的な演習であるため、設計パターンへの参照をいただければ幸いです。

回答:


7

ベストプラクティスは、Interceptorパターンと呼ばれるものを使用して、保護された領域への呼び出しを傍受することです。

これは、アクセスエントリポイントに適用されるAOPまたは横断的関心事を使用することで実現できます。

被験者は、誰がそれを見ることができるかについて決して知っているべきではありません。これは、不必要に同じ機能への直接アクセスメカニズムを提供しない限り、不必要に対象コードを複雑にし、必要になる理由はありません。

呼び出し元と呼び出し先は、拒否の処理を除いて、アクセスについて知らないことが望ましいです。ただし、問題は、実装しているシステムと、呼び出し元のセキュリティ資格情報/プリンシパルにアクセスする方法によって異なります。たとえば、SOAPシステムでは、この情報はSOAPメッセージのヘッダーに追加されますが、Windowsシステムでは、Windows認証メカニズムを介して利用できます。

AOPまたはインターセプターパターンアプローチを使用する場合、必要な例外をスローし、スローされた例外を処理するのはクライアント(呼び出し元)です。

このようにして、知識や機能を混ぜ合わせることなく、クライアント、サービス、認証コードを分離しておくことができます。



2

私はあなたのオプション3が最も近いと思いますが、usersubjectについて問い合わせる代わりに、usersubjectをアクセスコントローラに渡す必要があります。

class Subject {
    public function display(user) {
        if(!accessController.checkAccess(this, user, AccessControl.Read)) {
            display403(); //Or other.. eg, throw an error..
        }
    }
}

アクセスコントローラーは、アクセス権セットの取得と、アクセスが十分かどうかのチェックの両方を担当する必要があります。このようにして、ユーザーおよびサブジェクトの両方から分離して、アクセスコントローラーのストレージロジックとチェックロジックの両方を分離します。

例から欠落している可能性のある他の要素は、実行されている操作です。あなたが持つかもしれないので、いくつかのユーザーは、などいくつかのデータを読んではなく、更新する、削除、実行する権利を有していてもよいcheckAccess:三つのパラメータを持つアクセスコントローラに方法をusersubjectoperation。またcheckAccess、アクセスが許可されなかった理由に関する情報を返すために、いくつかの追加情報を提供することもできます。

たとえば、これらすべてを後でアクセスコントローラーに委任すると、アクセス許可の表示方法を置き換えることができます。あなたは役割ベースのアクセス制御から始めて、後でクレームベースに移行するかもしれません。権限を単純な構造で保存し、最初に階層的なグループ/ロールと、さまざまな種類のサブジェクトに許可される操作を追加します。許可セットをインターフェースに入れないことは、これを可能にするのに役立ちます。

これをプラグインするためにAOPを使用するか定型コードを使用するかは、私の意見ではそれほど重要ではありません。

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