2

次のような状況があります: 私のアプリケーションの承認メカニズムは、Spring セキュリティを使用して実装されています。中央クラスはAccessDecisionManagerを実装し、ボーター (それぞれがAccessDecisionVoterを実装) を使用して、何らかのメソッドへのアクセスを許可するかどうかを決定します。投票を集計するアルゴリズムはカスタムです。

public class PermissionManagerImpl extends AbstractAccessDecisionManager {

    public void decide(
            Authentication authentication,
            Object object,
            ConfigAttributeDefinition config) throws AccessDeniedException {
        Iterator<?> iter = getDecisionVoters().iterator();
        boolean wasDenied = false;

        while (iter.hasNext()) {
            AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
            int result = voter.vote(authentication, object, config);

            switch (result) {
                // Some tallying calculations
            }
        }

        if (wasDenied) {
            throw new AccessDeniedException("Access is denied");
        }               
    }

}

あるメソッドへのアクセスを拒否すると、アプリケーションのクライアントは、アクセスが拒否された理由を正確に示す有益な例外を取得することに関心があります。これは、有権者から意思決定マネージャーに情報を渡すことを意味します。残念ながら、標準のAccessDecisionVoterが意思決定マネージャーに返す唯一の情報は、可能な戻り値 ( ACCESS_GRANTEDACCESS_ABSTAINまたはACCESS_DENIED ) の 1 つです。

それを行う最良の方法は何ですか?

ありがとう。

4

3 に答える 3

3

この場合、AccesssDecisionVoterインターフェイスは実際に を返しますint。確かに、組み込みの投票者の実装は、常にあなたが言及した3つの定数のうちの1つだけを返します(そして、これらは標準のアクセス決定マネージャーがチェックするものです)が、実際には返すべき余分なものはありません-RoleVoter例えばは拒否しますプリンシパルが必要な役割を持っていない場合にのみアクセスします。

投票者とアクセス決定マネージャーの両方に独自の実装を使用しているため、私が見ているように、いくつかのオプションを利用できます。

  1. 整数の他の値をエラー コードの形式として返します。とを典型ACCESS_GRANTED的な値として扱いますが、その他の整数はエラー コード付きの「アクセス拒否」として扱います。理想的には、利用可能なエラー コードのルックアップ テーブルを用意します。基本的には貧乏人の列挙型です。ACCESS_ABSTAINACCESS_DENIED
  2. 投票者内で、通常どおりに戻りACCESS_DENIED、パブリックにアクセス可能なプロパティ (投票者オブジェクト自体または静的にアクセス可能なフィールドのいずれか) にエラーの理由を設定します。マネージャーで、カスタム投票者からアクセスが拒否された場合は、プロパティをチェックして詳細を取得します。
  3. 上記のように、ボーター内でエラー プロパティを設定します。ただし、渡されるインスタンスが、Authenticationこの情報を設定/取得するのに適した場所を提供する独自のカスタム サブクラスの 1 つであることを確認してください。
  4. AccessDeniedException投票者自体から (または適切なサブクラス) をスローします。これは、アクセス決定マネージャーのロジックを前提としているため、理想的ではありません。ただし、このバブルをそのままにするか、必要に応じてマネージャー内でキャッチし (これにはカスタム サブクラスが適しています)、アクセスが実際に拒否された場合は再スローします (ProviderManagerクラスがそのlastException変数に対して行うことと同様のこと)。

これらのどれも、明らかに正しくてエレガントな答えとして際立っていませんが、最も適切なものから実行可能なものを得ることができるはずです. 理由を伝えるための有権者フレームワーク内に明示的なサポートがないため(これは基本的に単純なブール値の応答です)、これ以上のことはできないと思います。

于 2009-02-04T12:18:08.310 に答える
2

答えてくれた人々に感謝します。

私は、私が望んでいたことを実行し、標準の有権者 API を引き続き使用するための非常にエレガントな方法を見つけたと思います。AccessDecisionVoterの投票メソッドの 2 番目のパラメーターは、保護されたオブジェクトです。意思決定マネージャーと投票者の間で、このオブジェクトがラッパーである特定のクラス/インターフェースであるという契約を作成できます。これにより、元のセキュリティで保護されたオブジェクトを取得でき、投票者が拒否する追加情報を追加できます。アクセス。

他のフレームワークでもこのようなパターンを見ました。このソリューションには、他の可能なソリューションよりも次の利点があります。

  • 有権者はステートレスのままでいられるため、シングルトンにすることができます
  • AccessDecisionVoter の標準インターフェースが使用され、新しい戻り値は追加されません
  • 追加情報は、 AbstactDecisionManager決定メソッドの後に誰も使用しないため、自動的に破棄されるオブジェクトに保存されるため、クリーンアップ コードは必要ありません。

乾杯。

于 2009-02-05T11:48:32.003 に答える
1

AccessDecisionManager投票者を使用せずに直接実装することはできませんか? AccessDeniedExceptionその後、正しい情報で をスローできます。おそらくRoleVoters は、あなたの場合に使用する適切な抽象化ではありません。

于 2009-02-04T12:28:43.687 に答える