Java 아키텍처·Spring 용어 사전
보안SecurityFilterChain · 세션 vs JWT · CSRF

필터 체인

Spring Security가 요청을 가로채는 서블릿 필터들의 사슬. 컨트롤러에 닿기 전에 인증·인가가 끝난다.

Spring Security는 서블릿 필터들의 사슬로 동작한다. 컨트롤러에 닿기 전에 인증·인가가 끝난다.

어디에 끼어 있나

요청 → [ ... 서블릿 필터들 ... ]
         └ DelegatingFilterProxy → FilterChainProxy
                                     └ SecurityFilterChain (여러 필터)
       → DispatcherServlet → 인터셉터 → 컨트롤러

DispatcherServlet 이전이라는 게 중요하다 — 그래서 @RestControllerAdvice보안 필터에서 난 예외는 못 잡는다.

주요 필터 순서

SecurityContextPersistenceFilter 저장된 인증 정보를 꺼내 SecurityContext 에 넣는다 UsernamePasswordAuthenticationFilter 폼 로그인 처리 (커스텀 JWT 필터를 보통 여기쯤 끼운다)

  • ExceptionTranslationFilter — 인증 예외 → 401 · 인가 예외 → 403 으로 변환
  • AuthorizationFilter — 최종 인가 판단
@Bean
SecurityFilterChain chain(HttpSecurity http) throws Exception {
    return http
        .csrf(csrf -> csrf.disable())                       // 아래 참고
        .sessionManagement(s -> s.sessionCreationPolicy(STATELESS))
        .authorizeHttpRequests(a -> a
            .requestMatchers("/public/**").permitAll()
            .requestMatchers("/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated())
        .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
        .build();
}

401과 403을 구분한다

  • 401 Unauthorized — 누구인지 모른다 (인증 실패·토큰 없음)
  • 403 Forbidden — 누구인지는 아는데 권한이 없다 (인가 실패)

세션 vs JWT

세션JWT
상태서버가 보관무상태
확장세션 저장소 공유 필요(Redis)서버 간 공유 불필요
무효화즉시 가능어렵다 — 만료까지 유효
크기쿠키에 id만토큰 자체가 크다

JWT의 결정적 약점은 무효화다. 로그아웃·권한 회수·탈취 대응이 어렵다.

실무 절충

  • 액세스 토큰은 짧게 (수 분~수십 분)
  • 리프레시 토큰은 서버에 저장해 회수 가능하게
  • 리프레시 재사용이 감지되면 해당 사용자의 토큰을 전부 무효화

CSRF는 왜 끄고 언제 켜나

  • CSRF 공격은 '브라우저가 쿠키를 자동으로 붙인다' 는 성질을 노린다

  • 쿠키 기반 세션 인증 (폼 로그인·SSR) — → CSRF 보호를 켠다

  • Authorization 헤더로 토큰 전달 — → 자동 전송이 아니므로 위험이 없다 → 꺼도 된다

"REST API니까 끈다"가 아니라 "인증 정보를 쿠키로 자동 전송하지 않으니 끈다" 가 정확한 이유다. 토큰을 쿠키에 담는다면 다시 켜야 한다.

면접 함정

  • "JWT가 세션보다 안전하다" → 무효화가 어려워 오히려 탈취 대응이 약하다. 무상태 확장성이 장점이다.
  • "CSRF는 항상 끈다" → 쿠키 인증이면 반드시 켠다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — Spring Security — 인증·인가·필터체인·JWT