스프링 시큐리티의 필터 및 내부 인증 저장 흐름

프로젝트전공부·2024년 8월 26일

스피링기본

목록 보기
2/8

스프링 시큐리티(Spring Security)는 웹 애플리케이션의 보안을 책임지는 강력한 프레임워크로, 다양한 보안 필터를 통해 인증(Authentication)과 인가(Authorization)을 처리합니다. 아래에서는 스프링 시큐리티의 기본적인 인증 흐름과 필터들, 그리고 내부에서 인증 정보를 저장하는 과정을 디테일하게 설명하겠습니다.

  1. 스프링 시큐리티의 필터 체인
    스프링 시큐리티는 FilterChainProxy를 통해 다수의 보안 필터를 관리합니다. 이 필터들은 사용자 요청을 가로채어 인증 및 인가 과정을 거친 후, 요청을 처리하거나 거부합니다. 주요 필터들은 다음과 같습니다:

AuthorizationFilter (인가 필터): URL에 대한 접근 제한을 관리하는 필터입니다. 이 필터는 사용자가 요청한 URL에 대해 해당 사용자가 적절한 권한을 가지고 있는지 확인합니다. 사용자가 권한이 없으면, 접근을 거부합니다.

DefaultLoginPageGeneratingFilter: 디폴트 로그인 페이지를 생성하는 필터입니다. 만약 애플리케이션에서 사용자 정의 로그인 페이지를 제공하지 않는다면, 스프링 시큐리티는 이 필터를 통해 기본 로그인 페이지를 자동으로 생성합니다.

UsernamePasswordAuthenticationFilter: 사용자가 로그인 폼을 통해 제출한 사용자명과 비밀번호를 처리하는 필터입니다. 이 필터는 사용자 자격 증명(Username and Password)을 받아 UsernamePasswordAuthenticationToken을 생성합니다.

  1. 토큰 생성 및 인증 관리
    스프링 시큐리티에서 인증은 주로 토큰 기반으로 이루어집니다. 주요 과정은 다음과 같습니다:

UsernamePasswordAuthenticationToken: 사용자가 로그인 시 입력한 사용자명과 비밀번호를 포함하는 토큰입니다. 이 토큰은 Authentication 인터페이스를 구현하며, 스프링 시큐리티 내부에서 인증의 기본 단위로 사용됩니다.

AbstractAuthenticationToken: UsernamePasswordAuthenticationToken의 상위 클래스입니다. 이 클래스는 인증 관련 정보를 캡슐화하고 있으며, 인증이 완료되면 사용자의 권한 정보가 포함됩니다.

Authentication: 스프링 시큐리티에서 인증을 나타내는 인터페이스입니다. 인증이 완료된 후, 이 인터페이스를 구현한 객체가 SecurityContext에 저장됩니다.

  1. AuthenticationManager와 ProviderManager
    스프링 시큐리티의 인증 흐름에서 핵심 역할을 하는 것이 AuthenticationManager입니다. 이 매니저는 인증 요청을 처리하며, 주로 ProviderManager를 통해 실제 인증이 이루어집니다.

ProviderManager: 여러 AuthenticationProvider를 관리하며, 인증 요청이 들어오면 이들 중 하나에 인증을 위임합니다. ProviderManager는 for문을 사용하여 각각의 AuthenticationProvider에 인증을 시도하며, 인증이 성공하면 Authentication 객체를 반환합니다.
4. UserDetailsService와 PasswordEncoder
스프링 시큐리티에서 사용자 정보를 관리하고 비밀번호를 처리하는 핵심 컴포넌트는 UserDetailsService와 PasswordEncoder입니다.

InMemoryUserDetailsManager: 메모리 내에서 사용자 정보를 관리하는 구현체로, 테스트나 작은 규모의 애플리케이션에 적합합니다. UserDetailsService를 구현하며, 사용자 이름으로 사용자를 로드하고, 해당 사용자의 세부 정보를 반환합니다.

PasswordEncoder: 비밀번호를 암호화하고 비교하는 데 사용되는 인터페이스입니다. NoOpPasswordEncoder는 비밀번호를 평문으로 저장하는 간단한 구현체입니다. 실제 운영 환경에서는 BCryptPasswordEncoder와 같은 강력한 인코더를 사용하는 것이 일반적입니다.

DaoAuthenticationProvider: AuthenticationProvider의 한 구현체로, UserDetailsService를 사용하여 사용자 정보를 로드하고, PasswordEncoder를 통해 비밀번호를 검증합니다. 인증이 성공하면 Authentication 객체를 반환합니다.

  1. 전체 흐름 요약 및 다이어그램
    스프링 시큐리티의 기본 인증 흐름을 요약하면 다음과 같습니다:

사용자 요청: 사용자가 보호된 리소스에 접근하려고 시도합니다.
필터 체인: AuthorizationFilter와 DefaultLoginPageGeneratingFilter가 요청을 가로채고, 인증 여부를 확인합니다.
자격 증명 추출: UsernamePasswordAuthenticationFilter가 로그인 폼에서 사용자명과 비밀번호를 추출하여 UsernamePasswordAuthenticationToken을 생성합니다.
AuthenticationManager: ProviderManager가 인증 요청을 받아, DaoAuthenticationProvider를 통해 실제 인증을 시도합니다.
UserDetailsService와 PasswordEncoder: DaoAuthenticationProvider가 InMemoryUserDetailsManager를 통해 사용자 정보를 로드하고, PasswordEncoder를 통해 비밀번호를 검증합니다.
인증 성공: 인증이 성공하면 Authentication 객체가 생성되어 SecurityContext에 저장됩니다.
응답: 인증이 완료되면, 요청된 리소스에 접근할 수 있도록 응답이 반환됩니다.
이 흐름을 다이어그램으로 나타내면 다음과 같습니다:

Request →
Filters (AuthorizationFilter, DefaultLoginPageGeneratingFilter) →
Token (UsernamePasswordAuthenticationToken) →
Authentication Manager (ProviderManager) →
Provider (DaoAuthenticationProvider) →
User Details Service (InMemoryUserDetailsManager) →
Validation (PasswordEncoder) →
Authentication Result →
Response
스프링 시큐리티 구성 방법 (Lambda DSL)
Spring Security 6.1 이후, Spring Boot 3.1.0에서는 보안 구성을 더 간결하게 하기 위해 람다 DSL(Lambda DSL) 스타일을 권장합니다. 이 스타일은 기존 방식에 비해 코드 가독성을 높이고, 불필요한 중복을 줄이는 장점이 있습니다.

예제: 람다 DSL을 사용한 보안 설정
기존 방식:

java
코드 복사
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll();
람다 DSL 적용:

java
코드 복사
http {
authorizeHttpRequests {
authorize(anyRequest, authenticated)
}
formLogin {
loginPage = "/login"
permitAll()
}
}
람다 DSL을 적용하면, 코드는 더 읽기 쉽게 정돈되며, .and()와 같은 연결 메소드를 생략할 수 있습니다. 이로 인해 보안 설정을 더 간결하게 작성할 수 있습니다.

이 설명을 통해 스프링 시큐리티의 필터 체인, 인증 흐름, 주요 컴포넌트 및 새로운 람다 DSL 스타일에 대한 이해를 높일 수 있습니다. 스프링 시큐리티를 사용하여 웹 애플리케이션의 보안을 효과적으로 관리하고 설정할 수 있을 것입니다.

profile
프로젝트전에 해당 부분을 깊게 공부한것을 올려두는 벨로그

0개의 댓글