Spring Security는 웹 애플리케이션의 인증과 인가를 담당하는 프레임워크입니다. 이를 사용하여 애플리케이션의 보안 요구사항을 충족시킬 수 있습니다. 이번 글에서는 Spring Security를 사용하여 인가 및 접근 제어를 구현하는 방법에 대해 알아보겠습니다.
1. 의존성 추가
Spring Security를 사용하기 위해 먼저 의존성을 추가해야 합니다. Maven을 사용하는 경우 pom.xml
에 다음과 같이 의존성을 추가합니다.
<dependencies>
<!-- Spring Security Core -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
Gradle을 사용하는 경우 build.gradle
에 다음과 같이 의존성을 추가합니다.
dependencies {
// Spring Security Core
implementation 'org.springframework.boot:spring-boot-starter-security'
}
2. 보안 구성 파일 작성
Spring Security의 기본적인 구성은 WebSecurityConfigurerAdapter
를 확장하는 클래스를 생성하여 작성합니다. 이 클래스에서 인가 및 접근 제어를 구현할 수 있습니다.
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/dashboard")
.permitAll()
.and()
.logout()
.permitAll();
}
}
위의 예제에서는 configure()
메소드를 재정의하여 URL 패턴에 따른 인가 및 접근 제어를 설정했습니다. antMatchers()
메소드를 이용하여 특정 URL 패턴에 대한 접근을 설정하고, authenticated()
메소드를 이용하여 인증된 사용자만 접근을 허용하도록 설정했습니다.
또한, formLogin()
메소드를 이용하여 커스텀 로그인 페이지를 지정하고, 성공 시 이동할 페이지를 설정했습니다. logout()
메소드를 이용하여 로그아웃 처리도 설정할 수 있습니다.
3. 사용자 정의 인증 및 인가
Spring Security는 기본적으로 사용자 및 권한 정보를 데이터베이스에서 가져오지만, 사용자 정의 인증 및 인가를 구현할 수도 있습니다. 이를 위해 UserDetailsService
를 구현하고, AuthenticationProvider
를 설정해야 합니다.
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.util.ArrayList;
import java.util.List;
@Service
public class CustomUserDetailsService implements UserDetailsService {
private final PasswordEncoder passwordEncoder;
public CustomUserDetailsService(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 사용자 정보를 데이터베이스에서 가져오는 로직을 구현합니다.
// 임시로 사용자 정보를 생성하여 반환합니다.
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new User("test", passwordEncoder.encode("password"), authorities);
}
}
위의 예제에서는 UserDetailsService
인터페이스를 구현하고 loadUserByUsername()
메소드를 재정의하여 사용자 정보를 반환하는 로직을 구현했습니다. 사용자 정보를 데이터베이스에서 가져오도록 구현해야 합니다.
또한, AuthenticationProvider
를 설정해야 해당 사용자 정의 인증 로직을 사용할 수 있습니다. 이를 위해 WebSecurityConfigurerAdapter
를 확장한 클래스에서 configure()
메소드를 재정의하고, authenticationProvider()
메소드를 사용하여 인증 프로바이더를 설정합니다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final CustomUserDetailsService customUserDetailsService;
@Autowired
public SecurityConfig(CustomUserDetailsService customUserDetailsService) {
this.customUserDetailsService = customUserDetailsService;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(customUserDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
위의 예제에서는 authenticationProvider()
메소드를 사용하여 DaoAuthenticationProvider
를 설정하고, setUserDetailsService()
메소드를 이용하여 사용자 정의 인증 로직을 적용합니다. 또한, 비밀번호를 암호화하기 위해 BCryptPasswordEncoder
를 사용했습니다.
4. 참고 자료
- Spring Security Documentation
- Baeldung - Spring Security Tutorials
- Spring Guides - Securing a Web Application