Spring Security Architecture
✒️ 2025-07-01 08:11 내용 수정
참고 자료 : Spring Security Servlet Applications Architecture, Introduction to Spring Security Architecture
Spring Security의 특성
- SpringMVC에서 들어오는 모든 HTTP 요청은
DispatcherServlet을 통해 전달되며,DispatcherServlet은 요청들을 애플리케이션의 엔드포인트를 정의하는Controller클래스들에 전달한다.- Spring Framework, Servlet 참고.
- Spring Security는 HTTP 요청이
DispatcherServlet에 도달하기 전에Filter클래스들을 추가하여 개입한다.- Filter 참고.
- 즉 들어오는 모든 HTTP 요청은
Filter클래스들을 하나씩 거치며, 요청은DispatcherServlet에 도달하기 전에 Authentication과 Authorization 과정을 거치게 된다.
Architecture
- 클라이언트가 HTTP 요청을 전송하면 Spring Container는
FilterChain을 생성하고,FilterChain에는Filter와Servlet(Spring MVC에선DispatcherServlet)을 생성한다.Servlet은 단일HttpServletRequest와HttpServletResponse를 처리한다.Filter는 다음Filter이나Servlet로의 downstream을 막고,HttpServletRequest나HttpServletResponse를 수정한다.
1. DelegatingFilterProxy
Filter구현체이며, Servlet Container의 생명 주기와 Spring의ApplicationContext를 연결한다.FilterChain의 앞에 위치하며,ApplicationContext에서 얻은 Bean Filter의 정보를 사용하여Filter를 찾아준다.
2. FilterChainProxy
- 많은
Filter인스턴스들을SecurityFilterChain을 통해 대리(delegating)하는 특별한Filter다.SecurityFilterBean은FilterChainProxy가 등록한다.
FilterChainProxy는 Bean이기에 보통DelegatingFilterProxy내부에 위치한다.- Spring Security의 Servlet 지원의 시작점을 제공하기 때문에 troubleshooting 시
FilterChainProxy에 디버그 포인트를 추가하면 유용하다. - 보안과 관련된 필수 작업들을 처리한다.
SecurityContext의 메모리 누수 방지를 위한 clear 작업을 수행한다.- 보안 공격을 막기 위한 Spring Security
HttpFirewall을 애플리케이션에 적용한다.
RequestMatcher인터페이스를 사용하여HttpServletRequest을 기반으로SecurityFilterChain의 호출을 결정한다.- URL의 패턴 별로 호출할
SecurityFilter를 결정한다.
- URL의 패턴 별로 호출할
3. SecurityFilterChain
- Spring Security의 핵심으로, HTTP 요청을 처리하고
AuthenticationManager와 유효한 요청들을 상호작용하는Filter들의 모음이다. FilterChainProxy는SecurityFilterChain을 사용하여 현재 요청을 위한 Spring SecurityFilter인스턴스 중 어느 것을 사용할지 결정한다.- Session, JWT 등 인증 방식을 사용할 때 필요한 설정을 서비스 로직 구현으로부터 분리할 수 있는 환경을 제공한다.
4. SecurityFilter
- 웹 애플리케이션의 보안과 인증, 인가, 세션 관리 등과 같은 일을 담당한다.
- Filter 참고.
- 보통
SecurityFilterChain내의 Security Filter는 Bean으로 되어 있지만DelegatingFilterProxy대신FilterChainProxy를 통해 등록된다. Filter는 다운 스트림Filter객체와Servlet에 영향을 주기 때문에 각Filter가 호출되는 순서는 매우 중요하다.- 예를 들어 인증(Authentication) 처리
Filter는 인가(Authorization)Filter작동 전에 호출되어 한다.
- 예를 들어 인증(Authentication) 처리
- Security Filter는 보통
HttpSecurity인스턴스를 사용하여 선언한다.
@Configuration
@EnableWebSecurity // Security 자동 설정
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// CsrfFilter
.csrf(Customizer.withDefaults())
// AuthorizationFilter
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
// BasicAuthenticationFilter
.httpBasic(Customizer.withDefaults())
// UsernamePasswordAuthenticationFilter
.formLogin(Customizer.withDefaults());
return http.build();
}
}
| 클래스 | 설명 |
|---|---|
ChannelProcessingFilter |
HTTP나 HTTPS와 같은 프로토콜을 확인 |
SecurityContextPersistenceFilter |
사용자의 세션 기간동안 지속되는 인증 정보를 확인 |
UsernamePasswordAuthenticationFilter |
제공된 credentials를 확인하고, 유효한 경우 AuthenticationObject를 생성 |
| 인증이 필요한 URL 요청이 들어왔을 때 인증되지 않은 상태라면 로그인 페이지를 반환 | |
ConcurrentSessionFilter |
사용자가 이용할 수 있는 session의 개수를 조절하며, session 제한 초과 시의 경우도 처리 |
LogoutFilter |
로그아웃 요청에 개입하여 사용자의 session을 종료 |
RememberMeAuthenticationFilter |
로그아웃을 한 이후에도 session들이 사용자를 기억하도록 설정 |
AnonymousAuthenticationFilter |
인증되진 않았지만 애플리케이션의 몇몇 부분에 제한된 접근을 가질 수 있는 익명 사용자를 생성 |
SessionManagementFilter |
유효하지 않은 session, Session fixation 방지, 그리고 session과 연관된 다른 일들을 처리 |
ExceptionTranslationFilter |
예외를 인증되지 않은 응답(unauthenticated response)로 변환 |
FilterSecurityInterceptor |
사용자가 중요한 역할을 가졌는지 확인하고, 특정 리소스에 접근을 허가 설정 |
CsrfFilter |
CSRF 공격 방지를 위한 Filter |
Authentication Architecture and Components
1. AuthenticationManager
- 사용자의 신원을 확인하는 핵심 Component로, 인증 과정을 조율하고 실제 인증은
AuthenticationProvider에 위임한다.- Spring Security에서 Filter가 Authentication을 어떻게 진행할지 정의하는 API이며(즉 인터페이스), 가장 많이 사용하는 구현체는
ProviderManager이다. - 여러 개의
AuthenticationManager를 사용하여 복잡한 인증 과정을 구현할 수 있다.
- Spring Security에서 Filter가 Authentication을 어떻게 진행할지 정의하는 API이며(즉 인터페이스), 가장 많이 사용하는 구현체는
2. AuthenticationProvider
- 실제 인증을 진행하는 역할을 담당한다.
- 특정 로직이나 외부 시스템을 사용하여 인증을 진행하는 커스텀
AuthenticationProvider를 만들어 사용할 수도 있다.
| 클래스 | 설명 |
|---|---|
DaoAuthenticationProvider |
UserDetailsService를 사용하여 사용자의 정보를 DB에서 가져와 credential(자격증명)과 비교 |
LdapAuthenticationProvider |
LDAP 서버를 통한 인증에 사용 |
JwtAuthenticationProvider |
사용자의 JWT token을 검증할 때 사용 |
3. UserDetailsService
- 인증 과정동안 사용자의 정보를 추출하는 인터페이스로, DB로부터 사용자의 정보를 가져오기 위해
AuthenticationProvider와 함께 사용한다.
4. PasswordEncoder
- 비밀번호를 안전하게 저장 및 비교할 때 비밀번호 해시화 및 검증하는 역할을 담당한다.
| 클래스 | 설명 |
|---|---|
BCryptPasswordEncoder |
Spring Security에서 비밀번호 해시화에 일반적으로 추천하는 설정. 각 패스워드에 랜덤 솔트를 생성을 담당 |
NoOpPasswordEncoder |
어떤 해싱이나 암호화를 수행하지 않음. 비밀번호를 플레인 텍스트로 저장하기 때문에 매우 취약 |
StandardPasswordEncoder |
단방향 해시 알고리즘을 사용하기에 보안에 취약하여 추천하지 않음 |
MessageDigestPasswordEncoder |
비밀번호 해시화에 SHA-256과 같은 특정 메시지 다이제스트 알고리즘을 사용. 플레인 텍스트보단 안전하지만 BCrypt보단 강력하지 않아 현대 애플리케이션에선 권장하지 않음. |
SCryptPasswordEncoder |
BCrypt와 비슷한 해시 알고리즘 메모리를 많이 사용하도록 설계되어 특정 타입의 공격에 저항이 있음. |
5. SecurityContextHolder
- 요청-응답 생명주기 동안 사용자의 보안 context를 관리하는 클래스다.
- Spring Security로 인증한 사용자의 상세 정보를 저장하며,
SecurityContext를 가지고 있다.
6. SecurityContext
SecurityContextHolder로 획득 가능하고,Authentication를 가지고 있다.
// Spring 공식 예시
// SecurityContext
SecurityContext context = SecurityContextHolder.createEmptyContext();
// Authentication
Authentication authentication =
new TestingAuthenticationToken("username", "password", "ROLE_USER");
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
7. Authentication
SecurityContext에서 가져올 수 있는 현재 인증된 사용자 정보다.principal(접근 주체) : 사용자의 정보, 권한, 다른 특정 정보를 가지고 있으며, username/password 방식으로 인증할 때UserDetails인스턴스로 사용자를 식별한다.credentials(자격증명) : 주로 비밀번호 정보이며, 사용자 인증에 사용한 뒤엔 비운다.authorities: 사용자에게 부여한 권한을GrantedAuthority로 추상화하여 사용한다.GrantedAuthority: 사용자가 부여받은 고수준의 권한으로,Authentication.getAuthorities()로 객체를 가져올 수 있다.
인증 흐름
- 참고 자료 : boostcourse Spring Security 개요, Amigoscode Spring Security Architecture Explained, Introduction to Spring Security Architecture
- 클라이언트가 웹 사이트에 로그인을 시도한다.
SecurityFilterChain에서 요청에 개입한다.- 만약 인증이 안되었다면(로그인을 안 했다면)
AuthenticationManager에 요청을 전송하고, credential(자격 증명)이 일치한다면AuthenticationManager는 자격 증명이 성공했음을 표시하는Authentication객체를 생성한다. AuthenticationManager는 생성된Authentication객체를 사용하여 사용자의 credential(자격 증명)을 검증한다.AuthenticationProvider는PasswordEncoder를 사용하여 비밀번호를 저장하고 비교한다.AuthenticationProvider는 사용자 정보를 가져오기 위해UserDetailsService를 사용하여 DB에 정보를 요청한다.UserDetailsService가 DB에서 읽어온 정보를UserDetails로 구현한 객체를 반환한다.AuthenticationProvider가 사용자의 credential(자격 증명)을 저장되거나 DB로부터 가져온 데이터와 비교하고, 사용자에게 인증 과정의 결과를 성공/미인증 응답으로 전송한다.- 인메모리 세션 저장소인
SecurityContextHolder에Authentication객체를 저장한다.
