권한 관리의 중요성과 RBAC의 역할
백엔드 시스템에서 권한 관리는 핵심 구성 요소로, 개인 블로그의 인증부터 기업 시스템의 다중 역할 제어까지 확장 가능한 설계가 필요합니다. RBAC(Role-Based Access Control)는 가장 보편화된 권한 모델로, 대부분의 백엔드 시스템에 적용됩니다. 본문은 RBAC의 핵심 논리, 작동 원리, Java SSM 프레임워크 구현 방식을 설명합니다.
RBAC 도입 배경: 권한 관리의 문제점
직원, 관리자, 시스템 운영자 세 사용자 유형이 있는 기업 내부 시스템을 가정할 때:
- 직접 권한 할당의 문제점:
- 확장성 부족: "재무" 역할 추가 시 전체 권한 검사 코드 수정 필요
- 유지보수 복잡성: 사용자와 권한 직접 연결 시 직책 변경 시 일일이 권한 조정 필요
- RBAC의 해결책: 역할을 중간 계층으로 사용해 사용자와 권한을 분리. 역할에 권한을 할당하면 사용자에게 역할만 부여함으로써 유연성 확보
RBAC 핵심 구조: 구성 요소와 관계
기본 요소 (4가지)
| 구성 요소 | 설명 | 사례 |
|---|---|---|
| 사용자(User) | 시스템 이용자 | 사원 김과장 |
| 역할(Role) | 권한 집합 | 사원, 팀장 |
| 권한(Permission) | 구체적 작업 권한 | 개인정보 조회 |
| 세션(Session) | 사용자-역할 임시 연결 | 로그인 시 생성된 세션 |
관계 모델 (3계층)
- 사용자-역할 연결: 다대다 관계 (사용자 여러 역할 보유 가능)
- 역할-권한 연결: 다대다 관계 (역할에 다수 권한 부여 가능)
- 사용자-권한 간접 연결: 역할 통해 권한 획득
확장 제약 조건 (5가지)
- 역할 상호배제: 충돌 역할 동시 보유 불가
- 역할 계층 구조: 상위 역할이 하위 권한 상속
- 최소 권한 원칙: 업무 수행에 필수적인 권한만 부여
RBAC 구현 단계별 진화
- RBAC0: 기본 사용자-역할-권한 구조 (소규모 시스템 적용)
- RBAC1: 역할 계층 구조 추가 (대기업 조직도에 적합)
- RBAC2: 보안 제약 조건 적용 (금융 시스템 등 고보안 환경)
Java SSM 프레임워크 구현
데이터베이스 설계
-- 사용자 테이블
CREATE TABLE system_user (
user_id INT PRIMARY KEY AUTO_INCREMENT,
login_id VARCHAR(50) UNIQUE,
encrypted_pwd VARCHAR(100)
);
-- 역할 테이블
CREATE TABLE system_role (
role_id INT PRIMARY KEY,
role_label VARCHAR(50) UNIQUE
);
-- 권한 테이블
CREATE TABLE system_perm (
perm_id INT PRIMARY KEY,
perm_code VARCHAR(100) UNIQUE,
resource_path VARCHAR(200)
);
-- 사용자-역할 연결 테이블
CREATE TABLE user_role_link (
user_id INT,
role_id INT,
PRIMARY KEY (user_id, role_id)
);
-- 역할-권한 연결 테이블
CREATE TABLE role_perm_link (
role_id INT,
perm_id INT,
PRIMARY KEY (role_id, perm_id)
);
Java 엔티티 구조
public class SystemUser {
private Integer userId;
private String loginId;
private List<SystemRole> roles;
}
public class SystemRole {
private Integer roleId;
private String roleLabel;
private List<SystemPerm> permissions;
}
public class SystemPerm {
private Integer permId;
private String permCode;
private String resourcePath;
}
권한 검증 인터셉터
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object obj) {
SystemUser currentUser = (SystemUser) req.getSession().getAttribute("currentUser");
if (currentUser == null) {
res.sendRedirect("/auth/login");
return false;
}
String requestUri = req.getRequestURI();
for (SystemRole role : currentUser.getRoles()) {
for (SystemPerm perm : role.getPermissions()) {
if (perm.getResourcePath().equals(requestUri)) {
return true;
}
}
}
res.setStatus(HttpStatus.FORBIDDEN.value());
res.getWriter().print("Access Denied");
return false;
}
}
스프링 인터셉터 설정
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/secure/**"/>
<mvc:exclude-mapping path="/auth/**"/>
<bean class="com.security.AuthInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
RBAC 모델의 장단점
| 장점 | 단점 |
|---|---|
|
|