跳转至主要内容

Menu Permissions

我们首先介绍一个使用Spring Boot的菜单系统示例。 这个示例利用jCasbin来管理菜单权限。 最终,它的目标是抽象出一个专门用于菜单权限的中间件,可以扩展到Casbin支持的其他语言,如Go和Python。

1. 配置文件

你需要在policy.csv文件中设置角色和权限管理,以及菜单项之间的父子关系。 更多详情,请参考这个GitHub仓库

1.1 概述

使用policy.csv,你可以灵活地配置角色权限和菜单结构,以实现细粒度的访问控制。 这个配置文件定义了不同角色对各种菜单项的访问权限,用户和角色之间的关联,以及菜单项之间的层次关系。

1.2 权限定义(策略)

  • 策略规则:策略以p为前缀定义,指定角色(sub)和他们在菜单项(obj)上的权限(act),以及规则的效果(eft),其中allow表示权限被授予,deny表示权限被拒绝。

示例:

  • p, ROLE_ROOT, SystemMenu, read, allow表示ROLE_ROOT角色有权读取SystemMenu菜单项。
  • p, ROLE_ROOT, UserMenu, read, deny表示ROLE_ROOT角色被拒绝读取UserMenu菜单项。

1.3 角色和用户关联

  • 角色继承:用户-角色关系和角色层次结构以g为前缀定义。 这允许用户从一个或多个角色继承权限。

示例:

  • g, user, ROLE_USER表示用户user被分配了ROLE_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管理菜单权限时,父菜单和子菜单之间的权限关系遵循特定的继承规则,有两个重要的默认规则:

父菜单权限的继承

如果一个父菜单明确地被授予allow权限,那么它的所有子菜单也默认为allow权限,除非特别标记为deny。 这意味着一旦一个父菜单是可访问的,它的子菜单默认也是可访问的。

处理没有直接权限设置的父菜单

如果一个父菜单没有直接的权限设置(既没有明确允许也没有明确拒绝),但至少有一个子菜单明确被授予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的能力高效地管理访问权限。