Springboot

🚀 스프링부트에서 사용자 권한(Role-Based Access Control, RBAC) 적용 방법

수아파파's 2025. 2. 13. 21:46
반응형

1️⃣ RBAC란 무엇이며, 왜 필요한가?
2️⃣ 스프링부트에서 RBAC 적용 방법
3️⃣ RBAC를 활용한 API 권한 관리
4️⃣ 결론: RBAC 적용의 장점과 확장 가능성


1️⃣ RBAC란 무엇이며, 왜 필요한가?

🔹 RBAC(Role-Based Access Control)란?

RBAC(역할 기반 접근 제어)는 사용자의 역할(Role)에 따라 권한(Access)을 관리하는 방식이야.
즉, 사용자 개개인에게 직접 권한을 부여하는 것이 아니라, 역할(Role)을 할당하고, 역할에 따라 접근 권한을 결정하는 방식이지.

🔹 RBAC가 필요한 이유

보안 강화 → 모든 사용자에게 동일한 권한을 주지 않고, 필요한 권한만 부여
관리 용이 → 새로운 역할이 추가되더라도, 사용자별 권한을 일일이 수정할 필요 없음
유연성 → 관리자(Admin), 사용자(User), 운영자(Manager) 등 다양한 권한을 설정 가능

📌 RBAC 예제

역할(Role)설명API 접근 가능 여부

ROLE_ADMIN 최고 관리자 모든 API 접근 가능
ROLE_MANAGER 운영자 일부 관리 기능 가능
ROLE_USER 일반 사용자 기본 기능만 사용 가능

2️⃣ 스프링부트에서 RBAC 적용 방법

🔹 1. 권한(Role) 컬럼 추가 (DB 스키마 수정)

📌 사용자 테이블(User 테이블)에 role 컬럼 추가

CREATE TABLE users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(255) NOT NULL,
    password VARCHAR(255) NOT NULL,
    role VARCHAR(50) NOT NULL DEFAULT 'ROLE_USER'
);

📌 role 컬럼에 ROLE_USER, ROLE_ADMIN 등을 저장하여 RBAC 적용


🔹 2. Spring Security 설정 파일에서 RBAC 적용

📌 Spring Security의 SecurityConfig.java에서 역할(Role)별 API 접근 제어 설정

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeHttpRequests()
                .requestMatchers("/admin/**").hasRole("ADMIN")  // 관리자만 접근 가능
                .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")  // 사용자 & 관리자 접근 가능
                .requestMatchers("/public/**").permitAll()  // 누구나 접근 가능
                .anyRequest().authenticated()
            .and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);  // JWT 사용 시 세션 사용 X
        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

 

/admin/** 엔드포인트는 ROLE_ADMIN만 접근 가능
/user/** 엔드포인트는 ROLE_USER, ROLE_ADMIN 둘 다 접근 가능
JWT 인증을 사용하므로 SessionCreationPolicy.STATELESS 설정


🔹 3. 사용자 엔티티(User Entity)에 권한(Role) 추가

📌 User 엔티티 (User.java)

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import java.util.Set;

@Getter
@Setter
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;
    private String password;

    @Enumerated(EnumType.STRING)
    private Role role;
}

 

📌 Role Enum (Role.java)

public enum Role {
    ROLE_USER, ROLE_ADMIN
}

🔹 4. 로그인 시 JWT에 사용자 역할 추가하기

📌 JWT 생성 시 역할(Role) 포함 (JwtTokenProvider.java)

import io.jsonwebtoken.*;
import java.util.Date;
import java.util.Map;
import java.util.HashMap;

public class JwtTokenProvider {
    private final String SECRET_KEY = "mysecretkey";
    private final long EXPIRATION_TIME = 1000 * 60 * 60;  // 1시간

    // 🔹 JWT 생성 메서드
    public String generateToken(String username, String role) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("role", role);  // 역할(Role) 정보 추가

        return Jwts.builder()
                .setClaims(claims)
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }

    // 🔹 JWT에서 역할(Role) 추출
    public String getRoleFromToken(String token) {
        return (String) Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody()
                .get("role");
    }
}

JWT에 역할(Role) 정보를 포함하여 사용자 인증 시 역할을 확인할 수 있도록 함


3️⃣ RBAC를 활용한 API 권한 관리

🔹 1. 컨트롤러에서 역할 기반 API 관리

📌 관리자(Admin)만 접근 가능 API (AdminController.java)

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/admin")
public class AdminController {

    @PreAuthorize("hasRole('ADMIN')")
    @GetMapping("/dashboard")
    public String adminDashboard() {
        return "관리자 대시보드 접근 성공!";
    }
}

✅ @PreAuthorize("hasRole('ADMIN')") → 이 API는 ROLE_ADMIN만 접근 가능

📌 일반 사용자(User)만 접근 가능 API (UserController.java)


@RestController
@RequestMapping("/user")
public class UserController {

    @PreAuthorize("hasAnyRole('USER', 'ADMIN')")
    @GetMapping("/profile")
    public String userProfile() {
        return "사용자 프로필 접근 성공!";
    }
}

✅ @PreAuthorize("hasAnyRole('USER', 'ADMIN')") → 일반 사용자와 관리자 모두 접근 가능


4️⃣ 결론: RBAC 적용의 장점과 확장 가능성

🔹 RBAC를 적용하면?

보안 강화 → 역할(Role)별로 API 접근을 제한 가능
관리 용이 → 역할(Role) 기반으로 사용자 그룹을 쉽게 관리
확장성 높음 → 새로운 역할을 추가할 때, 개별 권한 수정 없이 적용 가능

🔹 확장 가능성

📌 OAuth2와 연동하여 역할 관리 → 소셜 로그인과 RBAC를 함께 활용 가능
📌 DB에 권한을 저장하여 동적으로 관리 → 역할(Role) 테이블을 만들어 유연한 권한 관리 가능
📌 JWT와 RBAC 결합 → JWT를 활용해 인증과 역할을 함께 관리하여 보안 강화

🔥 이제 RBAC를 적용하여 보안이 강화된 API를 개발해보자! 🚀

 

반응형