개발노트/Spring

[Spring] Security 인증(Authentication) 흐름 정리

dev-mylee 2025. 2. 18. 13:57

회사 프로젝트에서 Spring Security를 사용하면서 정리해본 인증 처리 흐름.

학원에서 배웠을 때는 단순히 UserDetailsService만 구현했었는데,

실제 프로젝트에서는 AuthenticationProvider까지 커스텀해서 사용하니까 확실히 다르다.

 

1. 기본 인증 흐름

HTTP Request → AuthenticationFilter → AuthenticationManager → AuthenticationProvider → UserDetailsService

이게 기본 흐름인데, 실제로는 크게 두 가지 방식으로 구현 가능:

  1. 기본 Provider + UserDetailsService 구현
    • 학원에서 했던 방식
    • UserDetailsService만 구현하면 나머지는 Spring Security가 알아서 처리
    • 간단한 인증만 필요할 때 사용하기 좋음
    • DaoAuthenticationProvider가 기본으로 사용됨
  2. AuthenticationProvider 직접 구현
    • 현재 회사 프로젝트에서 사용 중인 방식
    • 인증 과정을 완전히 커스터마이징 가능
    • 로그인 이력 남기기, 특별한 검증 로직 추가 등에 용이
    • UserDetailsService와 함께 구현해야 함

 

 

2. Security 설정 방식 비교

학원에서 배운 Java Config 방식

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> {
                auth.requestMatchers("/", "/member/join", "/css/**").permitAll()
                    .anyRequest().authenticated();
            })
            .formLogin(form -> {
                form.loginPage("/member/login")
                    .loginProcessingUrl("/member/login")
                    .defaultSuccessUrl("/")
                    .failureUrl("/member/login?error");
            })
            .logout(logout -> {
                logout.logoutUrl("/member/logout")
                       .logoutSuccessUrl("/");
            });
            
        return http.build();
    }
}

 

  • Spring Boot 3.x에서 주로 사용
  • 체이닝 방식으로 설정이 깔끔함
  • IDE에서 자동완성 지원이 잘 됨
  • 설정 변경 시 바로 반영됨

 

회사 프로젝트의 XML 설정 방식

<security:http>
    <form-login 
        login-processing-url="/login"
        username-parameter="userId"
        password-parameter="userPw"
        login-page="/login/form"
        authentication-failure-url="/login/form?fail=true"
        authentication-success-handler-ref="loginSuccessHandler"
        default-target-url="/"
    />
</security:http>

 

 

  • 레거시 프로젝트에서 많이 사용
  • 설정 변경 시 서버 재시작 필요
  • 스프링 시큐리티 버전 업그레이드가 까다로움
  • XML 문법 오류 찾기가 어려움

 

 

3. 회사 프로젝트에서 구현한 방식

Custom Provider에서 하는 일

  • 로그인 시도 이력 남기기 (성공/실패 모두)
  • IP 정보 저장
  • 실패 사유 기록
  • 권한 정보 세팅

UserDetailsService에서 하는 일

  • 실제 DB에서 사용자 조회
  • 계정 잠금 여부 체크
  • 권한 정보 가져오기

 

 

4. 알게 된 점들

  1. SecurityContext는 ThreadLocal 기반이라 멀티쓰레드 환경에서도 안전
  2. AuthenticationProvider 인터페이스 구현
    • authenticate()와 supports() 두 메서드를 모두 구현해야 함
    • authenticate(): 실제 인증 로직 처리
    • supports(): 해당 Provider가 처리할 수 있는 인증 타입 명시 (예: form 로그인은 UsernamePasswordAuthenticationToken)
  3. 실제로는 성공/실패 handler도 많이 커스텀함
    • 특히 실패했을 때 어떤 에러메시지 보여줄지
  4. 설정 방식의 차이가 생각보다 큼
    • Java Config가 확실히 편한데, 회사 레거시는 XML이라 어쩔 수 없음
    • 나중에 마이그레이션 하면 좋을 것 같음
  5. 세션 관리가 은근히 신경 쓸 게 많음
    • 중복 로그인 처리
    • 세션 만료 시간
    • 로그아웃 처리