2

SpringSecurityまたはShiroのいずれかを使用して「資格」の概念を処理するための最良の方法についての意見に興味があります。

たとえば、次のような署名を持つJAX-RSエンドポイントを想像してみてください。

AccountDetails getAccountDetails(String accountId);

Spring Securityを使用して、次のような実装に注釈を付けることができます。

@Secured(AUTHORIZED_USER)
public AccountDetails getAccountDetails(String accountId) { ... }

またはシロを使用して、

@RequiresAuthentication
public AccountDetails getAccountDetails(String accountId) { ... }

ただし、私が探しているのは、ユーザーが特定のアカウントIDにアクセスする権限を持っていることを確認する方法に関する「ベストプラクティス」に関するいくつかの推奨事項です(これは「資格管理」と呼ばれます)。

私はいくつかの異なるアプローチを想像することができました:

@Secured(AUTHORIZED_USER)
@AccountEntitled
public AccountDetails getAccountDetails(@Account String accountId) { ... }

(これは、Spring Securityを使用するのは完全に簡単ではないと思いますが、間違っていると思います)。

または、ドメインオブジェクトを導入し、現在のセキュリティコンテキストで保持されている原則によってユーザーがそのアカウントを表示できる場合にのみ、をに変換するAccountIdことに成功するファクトリを導入することを想像できます。しかし、それは少し厄介になり始めます。StringAccountId

全体として、私はここで新しい概念を発明したくありません。これはパンとバターのようなもののようですが、ここでのベストプラクティスに関する信頼できる推奨事項を見つけることができませんでした。

提案をありがとう。

4

1 に答える 1

1

あなたがやろうとしているのは、特定のアカウントに行レベルのセキュリティを実装することのようです。この問題の潜在的な解決策について説明している他のStackoverflowの質問(Javaで行レベルのセキュリティを実装する方法データベースに依存しない行レベルのセキュリティソリューション)があります。さらに、最初の回答で提供されているリンクでは、SpringとHibernateを使用した行レベルのセキュリティの実装について説明しています。ただし、上位の回答では、データベースレベルで直接行レベルのセキュリティを実装することをお勧めします。

シロと一緒に仕事をしたことで、それは可能だと言えます。ただし、説明する機能のタイプに対応するには、独自のセキュリティ構造(レルム、アクセス許可、注釈)を実装する必要があります。1つのアプローチは、最後の例にあるものと同様のアノテーションを追加して、メソッドに権限チェックが必要であることを示すことです。この注釈はインターセプターに関連付けられ、インターセプターは適切なアクセス許可を生成してから、セキュリティフレームワークを呼び出してアクセス許可を確認します。

こんな感じになります。

方法:

@RequiresAuthorization
@Entitled
public AccountDetails getAccountDetails(@Account String accountId) {...}

インターセプター:

@Interceptor
@Entitled
public class EntitledInterceptor {
    @AroundInvoke
    public void interceptOrder(InvocationContext ctx) {
        // return type is AccountDetails 
        // parameter[0] is acccoundId
        Permission p = new CustomPermission(context.getMethod().getReturnType(),
                                            ctx.getParameters()[0]);
        if(SecurityUtils.getSubject().isPermitted(p)){
          return ctx.proceed();
        } else {
         throw new RowLevelSecurityException("No access!");
        }
}

レルム:

public boolean isPermitted(SubjectPrincipals principal, Permission p){
    if( p instanceof CustomPermission){
        CustomPermission cp = (CustomPermission) p;
        Class<?> type = cp.getType(); //AccountDetails
        Integer id = cp.getId(); //accountId
        Integer userId = principal.getPrimaryPrincipal(); //or username
        customPermissionCheckingLogic(userId, type, id);
    }
}

明らかに、この実装はCDIに依存しており、提供されたオブジェクトタイプに基づいてチェックするテーブルを決定する方法があります(JPAアノテーションはこの点で機能します)。さらに、Shiroの注釈スキャンに接続して、ここで行ったよりも直接/ネイティブのアクセス許可機能を提供する方法があるかもしれません。

CDIインターセプターに関するドキュメント。

于 2013-06-20T20:06:22.240 に答える