メインコンテンツにスキップ

Menu Permissions

まず、メニューシステムを特徴とするSpring Bootの例を紹介します。 この例では、メニュー権限を管理するためにjCasbinを活用しています。 最終的には、メニュー権限に特化したミドルウェアを抽象化することを目指しており、CasbinがサポートするGoやPythonなどの他の言語にも拡張可能です。

1. 設定ファイル

policy.csvファイルでロールと権限の管理を設定する必要があり、メニューアイテム間の親子関係も設定します。 詳細については、このGitHubリポジトリを参照してください。

1.1 概要

policy.csvを使用することで、役割の権限とメニュー構造を柔軟に設定し、詳細なアクセス制御を行うことができます。 この設定ファイルは、異なる役割に対する各メニューアイテムのアクセス権限、ユーザーと役割の関連付け、およびメニューアイテム間の階層関係を定義します。

1.2 権限定義(ポリシー)

  • ポリシールール: ポリシーはpプレフィックスで定義され、役割(sub)とその権限(act)、メニューアイテム(obj)、およびルールの効果(eft)が指定されます。ここで、allowは権限が許可され、denyは拒否されることを示します。

例:

  • p, ROLE_ROOT, SystemMenu, read, allowは、ROLE_ROOT役割がSystemMenuメニューアイテムに対する読み取りアクセス権を持つことを意味します。
  • p, ROLE_ROOT, UserMenu, read, denyは、ROLE_ROOT役割がUserMenuメニューアイテムに対する読み取りアクセス権を拒否されることを意味します。

1.3 役割とユーザーの関連付け

  • 役割の継承: ユーザーと役割の関係および役割の階層は、gプレフィックスで定義されます。 これにより、ユーザーは1つまたは複数のロールから権限を継承できます。

例:

  • g, user, ROLE_USER は、ユーザー userROLE_USER ロールに割り当てられていることを意味します。
  • g, ROLE_ADMIN, ROLE_USER は、ROLE_ADMINROLE_USER から権限を継承することを意味します。

1.4 メニューアイテムの階層

  • メニューの関係: メニューアイテム間の親子関係は g2 プレフィックスで定義され、メニューの構造を構築するのに役立ちます。

例:

  • g2, UserSubMenu_allow, UserMenu は、UserSubMenu_allowUserMenu のサブメニューであることを示します。
  • g2, (NULL), SystemMenu は、SystemMenu にサブメニューアイテムがないことを示し、トップレベルのメニューアイテムであることを意味します。

1.5 メニュー権限の継承とデフォルトルール

jCasbinでメニューの権限を管理する際、親メニューと子メニューの権限関係は特定の継承ルールに従い、2つの重要なデフォルトルールがあります:

親メニューの権限の継承:

親メニューが明示的にallow権限が付与されている場合、そのすべてのサブメニューも特にdenyとマークされていない限り、デフォルトでallow権限が適用されます。 これは、親メニューがアクセス可能になると、そのサブメニューもデフォルトでアクセス可能であることを意味します。

直接の権限設定がない親メニューの扱い:

親メニューに直接の権限設定(明示的に許可または拒否されていない)がないが、少なくとも1つのサブメニューが明示的にallow権限が付与されている場合、その親メニューは暗黙的にallow権限を持つと見なされます。 これにより、ユーザーはこれらのサブメニューに移動できます。

1.6 特別な権限継承ルール

権限の継承に関して、特にdeny権限が関与するシナリオでは、システムのセキュリティと権限の正確な制御を確保するために、以下のルールに従う必要があります:

明示的な拒否とデフォルトの拒否の区別:

ROLE_ADMINのようなロールがAdminSubMenu_denyのようなメニューアイテムへのアクセスを明示的に拒否されている場合(denyとマークされている)、このロールが別のロール(例:ROLE_ROOT)によって継承されたとしても、継承するロールは拒否されたメニューアイテムへのアクセスを許可されません。 これにより、ロールの継承によって明示的なセキュリティポリシーが迂回されることがなくなります。

デフォルト拒否権限の継承:

逆に、ロールがメニューアイテム(例:UserSubMenu_deny)へのアクセスを拒否しているが、これがデフォルトである場合(明示的にdenyとマークされていないが、明示的にallowされていないため)、このロールが別のロール(例:ROLE_ADMIN)によって継承されると、継承するロールはデフォルトのdenyステータスを上書きし、これらのメニューアイテムへのアクセスを許可することができます。

1.7 例の説明

ポリシー:

p, ROLE_ROOT, SystemMenu, read, allow
p, ROLE_ROOT, AdminMenu, read, allow
p, ROLE_ROOT, UserMenu, read, deny
p, ROLE_ADMIN, UserMenu, read, allow
p, ROLE_ADMIN, AdminMenu, read, allow
p, ROLE_ADMIN, AdminSubMenu_deny, read, deny
p, ROLE_USER, UserSubMenu_allow, read, allow

g, user, ROLE_USER
g, admin, ROLE_ADMIN
g, root, ROLE_ROOT
g, ROLE_ADMIN, ROLE_USER

g2, UserSubMenu_allow, UserMenu
g2, UserSubMenu_deny, UserMenu
g2, UserSubSubMenu, UserSubMenu_allow
g2, AdminSubMenu_allow, AdminMenu
g2, AdminSubMenu_deny, AdminMenu
g2, (NULL), SystemMenu
メニュー名ROLE_ROOTROLE_ADMINROLE_USER
SystemMenu
UserMenu
UserSubMenu_allow
UserSubSubMenu
UserSubMenu_deny
AdminMenu
AdminSubMenu_allow
AdminSubMenu_deny

2. メニュー権限制御

特定のユーザー名でアクセス可能なすべてのメニューアイテムのリストは、MenuService で利用可能な findAccessibleMenus() 関数を通じて特定できます。 特定のユーザーが指定されたメニューアイテムにアクセスする権限を持っているかどうかを確認するために、checkMenuAccess() メソッドを利用できます。 このアプローチにより、jCasbin の能力を活用してアクセス権を効率的に管理することで、メニュー権限が効果的に制御されます。