현대 웹 애플리케이션에서는 보안이 중요한 요소이며, Spring Security는 강력한 인증 및 권한 관리 기능을 제공합니다. 이번 글에서는 Spring Security를 활용하여 사용자 인증(Authentication) 및 **권한 관리(Authorization)**를 구현하는 방법을 심층적으로 분석하고, 실무에서의 활용 방안을 설명하겠습니다.
Spring Security는 Spring 기반 애플리케이션의 보안을 강화하는 프레임워크로, 다음과 같은 기능을 제공합니다.
Spring Boot 프로젝트에서 손쉽게 적용할 수 있도록 기본적인 보안 설정을 제공합니다.
Spring Security를 프로젝트에 추가하려면 의존성을 추가해야 합니다.
1) Spring Boot 프로젝트에 Spring Security 추가
pom.xml
에 Spring Security 관련 의존성을 추가합니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2) 기본 보안 설정
Spring Security를 추가하면 기본적인 로그인 인증이 자동 적용됩니다. 기본적으로 /login
페이지가 제공되며, user
계정과 자동 생성된 비밀번호로 로그인할 수 있습니다.
로그인 시 생성된 기본 비밀번호 확인
Using generated security password: a1b2c3d4e5
사용자 정의 보안 설정을 위해 SecurityConfig 클래스를 작성해야 합니다.
사용자 인증을 위해 Spring Security의 UserDetailsService를 활용하여 사용자 정보를 저장하고 검증할 수 있습니다.
1) 사용자 정보 저장 (UserDetailsService 구현)
import org.springframework.security.core.userdetails.User;
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;
import java.util.Collections;
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if ("admin".equals(username)) {
return new User("admin", "{noop}password", Collections.emptyList());
}
throw new UsernameNotFoundException("User not found");
}
}
{noop}
: 비밀번호를 암호화하지 않음을 의미하며, 실제 환경에서는 BCrypt 등의 암호화를 적용해야 합니다.loadUserByUsername
: 사용자의 인증 정보를 데이터베이스에서 가져오는 역할을 합니다.2) 보안 설정 (SecurityConfig 작성)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
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 {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin").hasRole("ADMIN")
.requestMatchers("/user").hasRole("USER")
.anyRequest().authenticated()
)
.formLogin()
.and()
.logout();
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
authorizeHttpRequests()
: 특정 URL에 대한 접근 권한을 설정합니다.formLogin()
: 기본 로그인 폼을 활성화합니다.logout()
: 로그아웃 기능을 활성화합니다.BCryptPasswordEncoder()
: 비밀번호를 안전하게 저장하도록 설정합니다.
4. 권한(Role) 기반 접근 제어 (Authorization)
Spring Security는 **역할(Role)**을 기반으로 사용자의 접근을 제어할 수 있습니다.
1) 사용자 역할 설정
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.List;
public class CustomUserDetails extends User {
public CustomUserDetails(String username, String password, String role) {
super(username, password, List.of(new SimpleGrantedAuthority(role)));
}
}
2) 권한 확인 예제
컨트롤러에서 @PreAuthorize
애너테이션을 사용하여 역할 기반 접근을 제한할 수 있습니다.
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/admin")
@PreAuthorize("hasRole('ADMIN')")
public String adminEndpoint() {
return "Admin Access";
}
@GetMapping("/user")
@PreAuthorize("hasRole('USER')")
public String userEndpoint() {
return "User Access";
}
}
5. 문의 내용 예시 및 답변
1. Spring Security에서 JWT를 활용한 인증을 적용하려면 어떻게 해야 하나요?
답변: JWT(JSON Web Token)를 활용하면 세션을 유지하지 않고 인증할 수 있습니다. spring-security-oauth2
및 jjwt
라이브러리를 활용하여 JWT 인증을 구현할 수 있습니다.
2. OAuth2 기반의 소셜 로그인을 Spring Security에서 어떻게 적용하나요?
답변: Spring Security의 spring-security-oauth2-client
라이브러리를 활용하면 Google, Facebook 등의 OAuth2 인증을 쉽게 구현할 수 있습니다.
3. Spring Security에서 CSRF 보호를 비활성화할 수 있나요?
답변: 기본적으로 Spring Security는 CSRF 보호를 활성화합니다. API 서버에서 CSRF가 필요 없을 경우 http.csrf().disable();
을 설정하여 비활성화할 수 있습니다.
일상에서 벗어나 진정한 휴식을 꿈꾼다면, 일본 하코네 온천 료칸만큼 매력적인 여행지도 드물 것입니다. 하지만 검색만…
디즈니랜드 여행을 앞두고 가장 중요한 고민 중 하나는 바로 “숙소 선택”입니다. 꿈같은 하루를 선물하고 싶은…
스이카 카드 발급 해야하는 이유 "도쿄 지하철 정복은 스이카 카드 없으면 절대 불가능합니다!" "이 카드…
리버 크루즈를 타야만 하는 이유 "오사카 여행에서 낮에는 활기찬 거리, 밤에는 화려한 네온사인으로 물든 도시를…
오사카 여행에 필수적인 교통패스인 오사카 교통패스에 대해 소개 하겠습니다. 일본 오사카 여행을 준비 중이시라면, 효율적인…
후쿠오카는 일본 여행지 중에서도 근교 여행지와 맛집, 쇼핑, 자연 풍경, 도시를 한 번에 즐길 수…