12

Web アプリケーションを保護するために Apache Shiro フレームワークを使用しようとしています (UI は Vaadin 6 に基づいています)。Shiro のサイトのすべての例に目を通し、何時間もグーグルで検索しましたが、次の要件に対処するためのきれいな方法が見つかりません。

アプリケーションが一種のプロジェクト管理ツールであると仮定すると、ユーザーは会社の階層内の特定の部門に属するアクティビティを作成します。各ユーザーは複数の部門で働く場合があり、部門ごとに異なるセキュリティ ロールを持っています。例:

部門 A - ユーザーはここでは「マネージャー」です
部門B
  部門 C - ユーザーは「管理者」です
    部門D

ユーザーは部門 A の「マネージャー」 ユーザーは部門 C の「管理者」 ユーザーは、部門 D (部門 C の先祖) の「管理者」ロールも継承する必要があります。

したがって、基本的な権限チェック (ある部門に属するアクティビティを表示したい場合) は次のようになります。

  1. ユーザーが表示しようとしているアクティビティが、ユーザーが役割を持っている部門に属しているかどうかを確認します。
  2. この部門での役割に基づいて、ユーザーが必要な権限を持っていることを確認してください。

私は現在、「システム全体の役割」だけでなく、「この特定の部門での役割」の概念を実装する方法を理解することに行き詰まっています。

上記の例を「activity:view:123」のような許可文字列に変換するにはどうすればよいですか? また、ビジネス ロジックで許可を確認するにはどうすればよいでしょうか。

もう 1 つの疑問は、Shiro での実装です。独自の実装を提供する労力を最小限に抑えるために、すぐに使えるソリューションを使用したいと思います。ただし、Shiro の組み込み実装は単純なケースのみを想定して設計されているようです。最初に複雑な承認の実装の例はありますか (上記のケースをカバーできます)?

4

1 に答える 1

3

この問題に対する私の解決策を説明したいだけです。これは誰かに役立つかもしれません。これは最適ではないかもしれないと思うので、よりクリーンな実装に関する提案はまだ受け付けています。

次のアクションを保護する必要があると仮定します。

  • アクティビティ:編集
  • アクティビティ:ビュー

また、アクセス許可がシステム全体ではなく、特定の部門での私の役割に依存していることも確認する必要があります。私がしたことは、レルムのユーザーに「部門に依存する」権限を明示的に追加したことです。例 (投稿の階層を参照):

  • DEP_A:アクティビティ:ビュー
  • DEP_C:アクティビティ:ビュー
  • DEP_C:アクティビティ:編集

あるアクティビティに対するアクションが許可されているかどうかを確認するたびに、確認する権限のリストを作成しています。例:

アクティビティ A は部門 D に属しています。「表示」したいです。チェックする権限は次のとおりです。

  • DEP_D:アクティビティ:ビュー
  • DEP_C:アクティビティ:ビュー
  • DEP_B:アクティビティ:ビュー

私が部門 C の管理者である場合、'DEP_C:activity:view' 権限を持っているため、チェックに合格します。これにより、会社構造階層で権利継承を実装できます。

権限チェックを担当するサービス クラスのコード スニペットを次に示します。

   @Override
   public void checkIfOperationPermitted( SecurityOperation operation, 
      Object object )
   {
      final Subject currentUser = SecurityUtils.getSubject();

      if(currentUser.isPermitted(
         SecurityOperation.SYSTEM_ADMIN.getPermissionString()) ||
         currentUser.hasRole( "admin" ))
      {
         // no need to check anything else,
         // admin is system wide role.
         return;
      }

      if(object instanceof Activity)
      {
         // Activity permissions fully depends on organization and
         // product hierarchies. PermissionResolver is just a class
         // which generates list of permission strings based on 
         // department activity is belonging to.
         Activity a = (Activity) object;
         List<String> permissionsToCheck = 
            permissionResolver.resolveHierarchicalPermissions(operation, a);
         boolean permitted = false;
         for(String permission: permissionsToCheck)
         {
            if(currentUser.isPermitted( permission ))
            {
               permitted = true;
               break;
            }
         }
         if(!permitted)
         {
            throw new UnauthorizedException( "Access denied" );
         }
      }
      else
      {
         // Check for system wide permissions
         currentUser.checkPermission( operation.getPermissionString() );
      }
   }

私が考えていた別の方法は、レルムにユーザーのそのようなすべての権限を追加することですが、会社の階層には一般に N 層を含めることができるため、これを拒否しました。これにより、特定のユーザーの権限リストの重複が大幅に増加します (メモリ使用量)。

于 2013-07-19T05:28:53.067 に答える