천천히 알아보는 코딩공부

[Spring Security] AuthenticationProvider, OncePerRequestFilter 본문

Java/SpringBoot

[Spring Security] AuthenticationProvider, OncePerRequestFilter

고기고기물고기 2025. 2. 4. 17:28

🔹 🚀  개념 정리

  AuthenticationProvider OncePerRequestFilter
언제 사용? 주로 세션(Session) 기반 인증 JWT 토큰 기반 인증
역할 로그인 요청 시 ID/PW 검증 및 세션 생성 모든 요청에서 JWT 검증 및 인증 정보 저장
어디에서 실행? AuthenticationManager가 호출할 때 실행 (/auth/login) HTTP 요청이 들어올 때마다 실행 (필터 체인에서 실행)
Security 설정 http.authenticationProvider(customAuthenticationProvider) http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
Spring Security 기본 구현체 DaoAuthenticationProvider UsernamePasswordAuthenticationFilter
로그인 이후 인증 방식 세션 (SecurityContextHolder에 저장됨) JWT (SecurityContextHolder에 저장됨)
 

✅ 정리: AuthenticationProvider vs OncePerRequestFilter

AuthenticationProvider → 세션(Session) 기반 인증에 사용
OncePerRequestFilter → JWT 기반 인증에 사용


🔹 🚀 최종 개념 정리


  AuthenticationProvider OncePerRequestFilter
언제 사용? 세션(Session) 기반 인증 JWT 토큰 기반 인증
역할 로그인 요청 시 ID/PW 검증 및 세션 생성 모든 요청에서 JWT 검증 및 인증 정보 저장
어디에서 실행? AuthenticationManager가 호출할 때 실행 (/auth/login) HTTP 요청이 들어올 때마다 실행 (필터 체인에서 실행)
Security 설정 http.authenticationProvider(customAuthenticationProvider) http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
Spring Security 기본 구현체 DaoAuthenticationProvider UsernamePasswordAuthenticationFilter
로그인 이후 인증 방식 세션 (SecurityContextHolder에 저장됨) JWT (SecurityContextHolder에 저장됨)

🔹 1. 세션(Session) 기반 인증 (Spring Security 기본)

  • 로그인 시 AuthenticationProvider가 AuthenticationManager를 통해 실행됨.
  • 인증이 성공하면 세션을 생성하고 SecurityContextHolder에 사용자 정보 저장.
  • 이후 요청에서는 세션 쿠키를 사용하여 인증 정보를 확인.

세션 기반 인증 설정 예제

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final CustomAuthenticationProvider customAuthenticationProvider;

    public SecurityConfig(CustomAuthenticationProvider customAuthenticationProvider) {
        this.customAuthenticationProvider = customAuthenticationProvider;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authenticationProvider(customAuthenticationProvider)  // 세션 기반 인증
            .formLogin()
                .loginProcessingUrl("/auth/login")  // 로그인 요청 URL
                .usernameParameter("username")
                .passwordParameter("password")
                .defaultSuccessUrl("/home", true)
                .failureUrl("/auth/login?error=true")
            .and()
            .logout()
                .logoutUrl("/auth/logout")
                .logoutSuccessUrl("/auth/login")
            .and()
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);  // 세션을 유지 (기본값)

        return http.build();
    }
}

✔ authenticationProvider(customAuthenticationProvider) 설정하여 세션 기반 인증 수행.
✔ SessionCreationPolicy.IF_REQUIRED → 필요할 때만 세션 생성 (기본값).
✔ 이후 요청에서는 세션을 사용하여 로그인 상태 유지.


🔹 2. JWT 기반 인증 (Stateless)

  • JWT는 세션을 사용하지 않고 Stateless 방식으로 동작.
  • 사용자가 로그인하면 JWT 토큰을 발급하고, 이후 요청마다 OncePerRequestFilter를 사용하여 인증 수행.
  • 즉, 모든 요청에서 HTTP 헤더의 JWT를 검사하여 SecurityContextHolder에 사용자 정보 저장.

JWT 기반 인증 설정 예제

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;

    public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter) {
        this.jwtAuthenticationFilter = jwtAuthenticationFilter;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)  // 세션 사용 안 함
            .and()
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) // JWT 필터 등록
            .authorizeHttpRequests()
                .requestMatchers("/api/**").authenticated()
                .anyRequest().permitAll();

        return http.build();
    }
}

✔ sessionCreationPolicy(SessionCreationPolicy.STATELESS) → 세션을 사용하지 않음.
✔ addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) → JWT 필터를 로그인 필터보다 먼저 실행.
✔ /api/** 요청마다 JWT를 검사하여 인증 정보 확인.

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtTokenProvider jwtTokenProvider;

    public JwtAuthenticationFilter(JwtTokenProvider jwtTokenProvider) {
        this.jwtTokenProvider = jwtTokenProvider;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        // 요청 헤더에서 JWT 토큰 가져오기
        String token = jwtTokenProvider.resolveToken(request);

        // 토큰이 유효한 경우, SecurityContext에 저장
        if (token != null && jwtTokenProvider.validateToken(token)) {
            Authentication auth = jwtTokenProvider.getAuthentication(token);
            SecurityContextHolder.getContext().setAuthentication(auth);
        }

        // 다음 필터로 요청 전달
        chain.doFilter(request, response);
    }
}

 

✔ 요청마다 JWT 토큰을 검사하여 SecurityContextHolder에 사용자 정보 저장.
✔ SecurityContextHolder에 인증 정보를 저장하면 컨트롤러에서 @AuthenticationPrincipal을 통해 사용자 정보 조회 가능.


🚀 최종 정리


사용 방식 AuthenticationProvider (세션 기반) OncePerRequestFilter (JWT 기반)
세션 사용 여부 ✅ 세션 사용 (SessionCreationPolicy.IF_REQUIRED) ❌ 세션 없음 (SessionCreationPolicy.STATELESS)
어디에서 사용? 로그인 요청 (POST /auth/login) 모든 요청 (/api/**)
어떻게 인증? 로그인 시 세션을 생성하여 관리 HTTP 헤더의 JWT 토큰을 확인하여 인증
필요한 설정 http.authenticationProvider(customAuthenticationProvider) http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
로그인 후 인증 정보 저장 위치 세션 (HttpSession) SecurityContextHolder에 직접 저장
사용 예제 일반적인 로그인/로그아웃 시스템 REST API 기반 JWT 인증 시스템

🚀 결론

세션 기반 인증 → AuthenticationProvider 사용 (SecurityContextHolder에 세션 저장)
JWT 기반 인증 → OncePerRequestFilter 사용 (모든 요청마다 SecurityContextHolder에 인증 정보 저장)
Spring Security에서 SessionCreationPolicy.STATELESS로 설정하면 AuthenticationProvider 방식이 아닌 JWT 인증을 사용해야 함.

🎯 즉, AuthenticationProvider는 세션 관리 방식에서 사용하고, OncePerRequestFilter는 JWT 방식에서 사용한다고 이해하면 됨! 🚀

Comments