この問題に対する私の解決策を説明したいだけです。これは誰かに役立つかもしれません。これは最適ではないかもしれないと思うので、よりクリーンな実装に関する提案はまだ受け付けています。
次のアクションを保護する必要があると仮定します。
また、アクセス許可がシステム全体ではなく、特定の部門での私の役割に依存していることも確認する必要があります。私がしたことは、レルムのユーザーに「部門に依存する」権限を明示的に追加したことです。例 (投稿の階層を参照):
- 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 層を含めることができるため、これを拒否しました。これにより、特定のユーザーの権限リストの重複が大幅に増加します (メモリ使用量)。