반응형

앞서 권한(Role)을 기반으로 한 API 인증과 권한 관리 방법을 살펴봤습니다. 이번 글에서는 다중 역할 처리와 **정책 기반 접근 제어(Policy-Based Access Control, PBAC)**를 구현하여 보다 유연하고 확장 가능한 권한 관리 시스템을 설계하는 방법을 다룹니다.


1. 다중 역할 처리 이해하기

현실적인 서비스에서는 사용자가 여러 역할을 동시에 가질 수 있습니다. 예를 들어:

  • 사용자는 USER이면서 CONTENT_CREATOR일 수 있습니다.
  • 관리자는 특정 PROJECT_MANAGER 역할을 추가로 수행할 수 있습니다.

다중 역할의 필요성

  • 팀원과 관리자가 같은 API를 사용하는 경우.
  • 하나의 계정으로 여러 권한을 실행해야 하는 경우.

2. 데이터베이스 설계

다중 역할을 지원하려면 역할을 별도의 테이블로 분리하여 관계를 설정해야 합니다.

데이터베이스 구조

Users 테이블

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(255) NOT NULL,
    password VARCHAR(255) NOT NULL
);

Roles 테이블

CREATE TABLE roles (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL
);

User_Roles 테이블

CREATE TABLE user_roles (
    user_id INT NOT NULL,
    role_id INT NOT NULL,
    FOREIGN KEY (user_id) REFERENCES users(id),
    FOREIGN KEY (role_id) REFERENCES roles(id),
    PRIMARY KEY (user_id, role_id)
);

3. 다중 역할 기반 권한 검사

JWT에 다중 역할 추가

사용자의 모든 역할 정보를 JWT에 포함시켜야 합니다.

JWT 생성

private String generateToken(User user, List<String> roles) {
    return Jwts.builder()
            .setSubject(user.getUsername())
            .claim("roles", roles) // 역할 배열 추가
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + 86400000)) // 1일
            .signWith(SignatureAlgorithm.HS512, SECRET_KEY)
            .compact();
}

JWT 파싱 및 역할 추출

Claims claims = Jwts.parser()
        .setSigningKey(SECRET_KEY)
        .parseClaimsJws(token)
        .getBody();

List<String> roles = claims.get("roles", List.class);

권한 검사 로직

다중 역할에 따라 API 접근을 제어합니다.

Authorization Filter 수정

private boolean isAuthorized(List<String> roles, String requestURI) {
    // 예: 특정 경로는 ADMIN 또는 MANAGER만 접근 가능
    if (requestURI.startsWith("/admin") && (roles.contains("ADMIN") || roles.contains("MANAGER"))) {
        return true;
    }
    // 예: /user 경로는 USER 역할만 허용
    if (requestURI.startsWith("/user") && roles.contains("USER")) {
        return true;
    }
    // 예: /public은 모든 사용자 허용
    if (requestURI.startsWith("/public")) {
        return true;
    }
    return false;
}

4. 정책 기반 접근 제어(PBAC)

PBAC는 JSON 또는 YAML로 정의된 정책을 기반으로 동적으로 접근 제어를 수행합니다.

PBAC의 장점

  • 정책 변경 시 코드 수정 없이 동작 가능.
  • 권한 조건을 데이터 기반으로 확장 가능.

정책 예제 (JSON)

{
  "policies": [
    {
      "resource": "/admin",
      "roles": ["ADMIN", "MANAGER"]
    },
    {
      "resource": "/user",
      "roles": ["USER", "ADMIN"]
    },
    {
      "resource": "/public",
      "roles": ["GUEST", "USER", "ADMIN"]
    }
  ]
}

PBAC 적용

JSON 정책 로드

public List<Policy> loadPolicies() {
    ObjectMapper mapper = new ObjectMapper();
    try (InputStream input = new FileInputStream("policies.json")) {
        return mapper.readValue(input, new TypeReference<List<Policy>>() {});
    } catch (IOException e) {
        throw new RuntimeException("Failed to load policies", e);
    }
}

PBAC 로직 적용

private boolean isAuthorized(List<String> roles, String requestURI) {
    List<Policy> policies = loadPolicies();
    for (Policy policy : policies) {
        if (requestURI.startsWith(policy.getResource())) {
            for (String role : roles) {
                if (policy.getRoles().contains(role)) {
                    return true;
                }
            }
        }
    }
    return false;
}

5. Postman을 통한 다중 역할 및 PBAC 테스트

  1. JWT 생성
    • /auth/login 요청으로 다중 역할을 포함한 JWT 토큰 생성.
  2. 권한이 없는 요청
    • /admin 경로를 USER 권한으로 요청 시 403 Forbidden 확인.
  3. 권한이 있는 요청
    • /admin 경로를 ADMIN 권한으로 요청 시 성공 확인.

6. 확장 사항

  • 시간 기반 정책: 특정 시간대에만 API 접근 허용.
  • 조건부 권한: API 호출 시 특정 매개변수를 만족해야 접근 허용.
  • Audit Log 추가: 누가 어떤 API에 접근했는지 기록.

결론

다중 역할과 정책 기반 접근 제어를 사용하면 더 복잡한 시나리오에서도 유연하게 권한 관리를 구현할 수 있습니다. 이는 대규모 시스템에서 보안과 유연성을 모두 만족시킬 수 있는 강력한 방법입니다.

반응형

+ Recent posts