반응형
전자정부프레임워크와 Spring Security를 사용하여 **역할 기반 권한 관리(RBAC)**를 구현하는 방법을 학습합니다.
RBAC는 보안의 핵심으로, 사용자가 수행할 수 있는 작업을 역할에 따라 제어하는 방식입니다.
1. 역할 기반 권한 관리의 개념
1-1. RBAC란?
- 역할(Role): 사용자의 직책이나 책임을 나타냅니다.
- 권한(Permission): 특정 리소스에 대한 작업 권한(읽기, 쓰기 등)을 정의합니다.
- 사용자(User): 역할을 부여받아 리소스를 제어합니다.
1-2. RBAC의 장점
- 보안 정책 관리가 용이함.
- 역할 변경 시 권한 자동 업데이트.
- 조직 구조에 맞는 보안 모델 제공.
2. 구현 계획
2-1. 요구사항 정의
- 관리자(admin)와 사용자(user)로 역할 분리.
- 관리자만 특정 리소스에 접근 가능하도록 제한.
- 사용자와 역할을 데이터베이스로 관리.
2-2. 구현 흐름
- 역할(Role)과 사용자(User) 엔티티 설계.
- 권한 부여를 위한 Spring Security 설정.
- 사용자 인증과 역할 기반 권한 검증 구현.
3. 구현 코드
3-1. 엔티티 설계
User 엔티티
import javax.persistence.*;
import java.util.Set;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles;
// Getters and Setters
}
Role 엔티티
import javax.persistence.*;
import java.util.Set;
@Entity
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany(mappedBy = "roles")
private Set<User> users;
// Getters and Setters
}
3-2. 저장소 설계
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
import org.springframework.data.jpa.repository.JpaRepository;
public interface RoleRepository extends JpaRepository<Role, Long> {
}
3-3. Spring Security 설정
UserDetailsService 구현
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
public CustomUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found");
}
return new CustomUserDetails(user);
}
}
CustomUserDetails 클래스
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.stream.Collectors;
public class CustomUserDetails implements UserDetails {
private final User user;
public CustomUserDetails(User user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toSet());
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
Spring Security 설정
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
private final UserDetailsService userDetailsService;
public SecurityConfig(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
.and()
.formLogin();
return http.build();
}
@Bean
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
}
4. 테스트
- 사용자 추가
- DB에 사용자 계정과 역할을 추가합니다.
- 비밀번호는 BCrypt를 사용하여 암호화합니다.
- 권한 테스트
- 관리자 경로(/admin/**)는 관리자만 접근 가능.
- 사용자 경로(/user/**)는 사용자 및 관리자 모두 접근 가능.
- 인증되지 않은 사용자는 로그인 페이지로 리다이렉트됩니다.
5. 마무리
이번 학습에서는 전자정부프레임워크와 Spring Security를 활용하여 역할 기반 권한 관리를 구현하였습니다.
RBAC를 통해 보안과 관리 효율성을 높일 수 있었습니다.
다음에서는 전자정부프레임워크에서 REST API 보안 강화를 학습합니다.
반응형
'개발 > 전자정부프레임워크' 카테고리의 다른 글
REST API와 CORS 설정 이해 및 구현 (0) | 2024.12.27 |
---|---|
전자정부프레임워크에서 REST API 보안 강화 (1) | 2024.12.26 |
전자정부프레임워크에서 인증 로그 관리 구현 (0) | 2024.12.26 |
다중 인증 방식 통합 구현 (JWT와 OAuth 2.0) (0) | 2024.12.26 |
OAuth 2.0 커스텀 인증 필터 구현 (0) | 2024.12.26 |