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, 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_ADMIN
이ROLE_USER
로부터 권한을 상속받았음을 의미합니다.
1.4 메뉴 항목 계층 구조
- 메뉴 관계: 메뉴 항목 간의 부모-자식 관계는
g2
접두사로 정의되어, 메뉴 구조를 구성하는 데 도움이 됩니다.
예시:
g2, UserSubMenu_allow, UserMenu
는UserSubMenu_allow
가UserMenu
의 하위 메뉴임을 나타냅니다.g2, (NULL), SystemMenu
는SystemMenu
에 하위 메뉴 항목이 없음을 나타내며, 이는 최상위 메뉴 항목임을 의미합니다.
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
MenuName | ROLE_ROOT | ROLE_ADMIN | ROLE_USER |
---|---|---|---|
SystemMenu | ✅ | ❌ | ❌ |
UserMenu | ❌ | ✅ | ❌ |
UserSubMenu_allow | ❌ | ✅ | ✅ |
UserSubSubMenu | ❌ | ✅ | ✅ |
UserSubMenu_deny | ❌ | ✅ | ❌ |
AdminMenu | ✅ | ✅ | ❌ |
AdminSubMenu_allow | ✅ | ✅ | ❌ |
AdminSubMenu_deny | ✅ | ❌ | ❌ |
2. 메뉴 권한 제어
주어진 사용자 이름으로 접근 가능한 모든 메뉴 항목의 목록은 MenuService에서 사용 가능한 findAccessibleMenus()
함수를 통해 확인할 수 있습니다. 특정 사용자가 지정된 메뉴 항목에 접근할 권한이 있는지 확인하려면, checkMenuAccess()
메소드를 사용할 수 있습니다. 이 접근 방식은 메뉴 권한이 효과적으로 제어되도록 보장하며, jCasbin의 기능을 활용하여 접근 권한을 효율적으로 관리합니다.