주요 콘텐츠로 건너뛰기

Menu Permissions

메뉴 시스템을 특징으로 하는 스프링 부트 예시를 소개하겠습니다. 이 예시는 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, allowROLE_ROOT 역할이 SystemMenu 메뉴 항목에 대한 읽기 권한을 가지고 있음을 의미합니다.
  • p, ROLE_ROOT, UserMenu, read, denyROLE_ROOT 역할이 UserMenu 메뉴 항목에 대한 읽기 권한이 거부되었음을 의미합니다.

1.3 역할과 사용자 연관성

  • 역할 상속: 사용자-역할 관계와 역할 계층 구조는 g 접두사로 정의됩니다. 이를 통해 사용자는 하나 이상의 역할로부터 권한을 상속받을 수 있습니다.

예시:

  • g, user, ROLE_USER는 사용자 userROLE_USER 역할을 부여받았음을 의미합니다.
  • g, ROLE_ADMIN, ROLE_USERROLE_ADMINROLE_USER로부터 권한을 상속받았음을 의미합니다.

1.4 메뉴 항목 계층 구조

  • 메뉴 관계: 메뉴 항목 간의 부모-자식 관계는 g2 접두사로 정의되어, 메뉴 구조를 구성하는 데 도움이 됩니다.

예시:

  • g2, UserSubMenu_allow, UserMenuUserSubMenu_allowUserMenu의 하위 메뉴임을 나타냅니다.
  • g2, (NULL), SystemMenuSystemMenu에 하위 메뉴 항목이 없음을 나타내며, 이는 최상위 메뉴 항목임을 의미합니다.

1.5 메뉴 권한 상속 및 기본 규칙

jCasbin으로 메뉴 권한을 관리할 때, 부모 메뉴와 자식 메뉴 간의 권한 관계는 특정 상속 규칙을 따르며, 두 가지 중요한 기본 규칙이 있습니다:

부모 메뉴 권한의 상속:

부모 메뉴가 명시적으로 allow 권한을 부여받으면, 특별히 deny로 표시되지 않는 한 모든 하위 메뉴도 기본적으로 allow 권한을 갖게 됩니다. 이는 한 번 부모 메뉴에 접근할 수 있게 되면, 그 하위 메뉴도 기본적으로 접근 가능하다는 것을 의미합니다.

직접 권한 설정이 없는 부모 메뉴 처리:

부모 메뉴에 직접 권한 설정이 없고 (명시적으로 허용되지도 거부되지도 않음) 하지만 적어도 하나의 하위 메뉴가 명시적으로 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
MenuNameROLE_ROOTROLE_ADMINROLE_USER
SystemMenu
UserMenu
UserSubMenu_allow
UserSubSubMenu
UserSubMenu_deny
AdminMenu
AdminSubMenu_allow
AdminSubMenu_deny

2. 메뉴 권한 제어

주어진 사용자 이름으로 접근 가능한 모든 메뉴 항목의 목록은 MenuService에서 사용 가능한 findAccessibleMenus() 함수를 통해 확인할 수 있습니다. 특정 사용자가 지정된 메뉴 항목에 접근할 권한이 있는지 확인하려면, checkMenuAccess() 메소드를 사용할 수 있습니다. 이 접근 방식은 메뉴 권한이 효과적으로 제어되도록 보장하며, jCasbin의 기능을 활용하여 접근 권한을 효율적으로 관리합니다.