14-1. 시큐리티 필터 체인 (Security Filter Chain)

박은서's avatar
Feb 25, 2026
14-1. 시큐리티 필터 체인 (Security Filter Chain)

1. Spring Security Filter Chain

💡
스프링 시큐리티의 본질
서블릿 필터 기반 보안 프레임워크 컨트롤러 이전 단계에서 요청을 가로채 인증/인가를 처리

1️⃣ 전체 구조 (큰 그림)

Client Request ↓ Servlet Container Filter Chain ↓ DelegatingFilterProxy ↓ FilterChainProxy (Spring Security) ↓ Security Filter Chain (여러 보안 필터) ↓ DispatcherServlet → Controller

1) DelegatingFilterProxy

  • 서블릿 필터와 스프링 빈을 연결하는 브리지
  • 실제 보안 처리는 스프링 빈에게 위임

2) FilterChainProxy (핵심)

  • 스프링 시큐리티의 중앙 허브
  • 여러 개의 SecurityFilterChain 중 매칭되는 체인 선택
  • 내부적으로 보안 필터들을 순서대로 실행

2️⃣ SecurityFilterChain이란?

특정 요청 패턴에 적용되는 필터 묶음.
@Bean SecurityFilterChain filterChain(HttpSecurity http) { ... }
✔ 요청 URL 기준으로 체인 선택 가능
예:
/api/** → JWT 인증 체인 /admin/** → 폼 로그인 체인

3️⃣ 동작 원리 (핵심 흐름)

1) 요청 진입

  • FilterChainProxy가 요청과 매칭되는 체인 선택

2) 인증 필터 실행

  • 인증 정보 추출 (세션 / JWT / Basic Auth 등)

3) SecurityContext 생성

  • 인증 성공 시 SecurityContextHolder 저장

4) 인가 검사

  • 접근 권한 확인

5) 컨트롤러 진입

4️⃣ 반드시 알아야 할 핵심 필터들

실제 필터는 많지만, 실무 핵심만 정리.

1) SecurityContextPersistenceFilter

  • 역할
    • 요청 시작 시 SecurityContext 로드
    • 요청 종료 시 저장
  • 중요 포인트
    • 세션 기반 인증의 핵심

2) UsernamePasswordAuthenticationFilter

  • 역할
    • 폼 로그인 처리
    • ID/PW → Authentication 객체 생성
  • 동작
    • Request → UsernamePasswordAuthenticationToken → AuthenticationManager → 인증 성공/실패

3) BasicAuthenticationFilter

  • 역할
    • HTTP Basic 인증 처리
  • 특징
    • Authorization 헤더 사용

4) BearerTokenAuthenticationFilter (JWT 환경)

  • 역할
    • Authorization: Bearer {token} 처리
  • 핵심
    • Stateless 인증의 핵심 필터

5) AnonymousAuthenticationFilter

  • 역할
    • 인증 정보 없을 때 익명 사용자 생성
  • 왜 필요?
    • null 대신 익명 객체 사용 → NPE 방지

6) ExceptionTranslationFilter

  • 역할
    • 인증/인가 예외 처리
  • 담당 예외
    • AuthenticationException → 로그인 유도
    • AccessDeniedException → 403 반환

7) FilterSecurityInterceptor ⭐ (인가의 핵심)

  • 역할
    • 최종 접근 권한 검사
  • 내부 처리
    • 권한 체크 → AccessDecisionManager 호출
  • 가장 중요한 필터 중 하나

5️⃣ 인증 관련 핵심 객체 이해

1) Authentication

  • 의미
    • 인증 상태 + 사용자 정보
  • 주요 구현체
    • UsernamePasswordAuthenticationToken
    • JwtAuthenticationToken 등

2) AuthenticationManager

  • 역할
    • 인증 처리 총괄
  • 실제 위임 대상
    • AuthenticationProvider

3) AuthenticationProvider

  • 역할
    • 실제 인증 로직 수행
    • DB 사용자 검증
    • JWT 검증

4) SecurityContextHolder ⭐

  • 역할
    • 현재 사용자 인증 정보 저장소
  • 중요 개념
    • ThreadLocal 기반
SecurityContextHolder.getContext().getAuthentication()

6️⃣ 필터 실행 순서가 중요한 이유

스프링 시큐리티는 순서 의존적 구조

1) 예

  • 인증 필터 → 인가 필터 순서 필수
  • 예외 필터는 인가 필터 앞에 위치

2) 순서가 잘못되면

  • 인증이 안 됨
  • 권한 체크 실패
  • 예외 처리 불능

7️⃣ 커스텀 필터 추가 시 필수 개념

http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
  • 언제 사용?
    • JWT 인증
    • API Key 인증
    • 로깅 / 트래킹
  • 핵심 전략
    • 방식
      의미
      addFilterBefore
      특정 필터 이전
      addFilterAfter
      특정 필터 이후
      addFilterAt
      교체

8️⃣ Stateless vs Stateful 차이

구분
Stateful (세션)
Stateless (JWT)
인증 저장
세션
토큰
서버 상태
유지
없음
필터 핵심
SecurityContextPersistenceFilter
BearerTokenAuthenticationFilter
확장성
낮음
높음

9️⃣ 실무에서 자주 발생하는 문제

1) 인증은 됐는데 SecurityContext가 비어 있음 🚨

  • 원인
    • 필터 순서 문제
    • context 저장 누락

2) JWT 필터가 동작 안 함 🚨

  • 원인
    • 체인 매칭 실패
    • addFilter 위치 오류

3) permitAll인데 인증 필터는 실행됨 🚨

  • 정상 동작임
    • 필터 체인 ≠ 인가 설정

🔟 실행 흐름

(A) 시작 준비 단계

1) SecurityContextPersistenceFilter

  • 요청이 들어오면 “이전 로그인 정보”를 꺼내서 준비
  • 세션 기반 : 세션에서 인증정보 로드
  • JWT 같은 Stateless : 보통 비어있을 수 있음(대신 뒤에서 토큰으로 채움)
➡️ 비유 : 출입기록부 열어보기

(B) “누구냐?”를 판단하는 인증 단계

  • 여기서부터는 프로젝트에 따라 다르게 동작

2) (선택) BearerTokenAuthenticationFilter (JWT일 때)

  • 요청 헤더에서 Authorization: Bearer 토큰을 찾음
  • 토큰 검증이 성공하면 “이 사용자는 누구다”를 확정하고 저장
➡️ 비유 : 모바일 탑승권(QR) 스캔

3) (선택) UsernamePasswordAuthenticationFilter (폼로그인일 때)

  • 로그인 요청(/login)이 들어오면
  • id/pw를 꺼내서 인증 처리
  • 성공하면 “이 사용자”로 확정하고 저장
➡️ 비유 : 직원에게 신분증+비밀번호로 확인받기

4) (선택) BasicAuthenticationFilter (Basic Auth일 때)

  • Authorization 헤더에서 Basic 인증 처리
➡️ 비유 : 간단 출입증(아이디/패스워드) 검사

(C) “없으면 익명 처리” 단계

5) AnonymousAuthenticationFilter

  • 위 단계까지 와도 “사용자 확정”이 안 됐으면
  • “익명 사용자”라는 표식을 만들어 넣음
중요 : 익명은 “로그인 상태”가 아니지만, 시큐리티는 null 대신 익명을 넣고 통일된 방식으로 처리함.
➡️ 비유: 방문객 스티커 붙여줌

(D) 문제 발생 시 처리하는 “안내데스크”

6) ExceptionTranslationFilter

  • 뒤에서 권한 검사하다가 문제가 생기면
    • 로그인 안 했으면 → 로그인 화면/401 처리
    • 권한 없으면 → 403 처리
  • “예외를 사용자에게 보여줄 결과”로 바꾸는 역할
➡️ 비유: 규정 위반 시 안내데스크로 보내기

(E) 마지막 관문: “여기 들어갈 권한이 있냐?”

7) FilterSecurityInterceptor ⭐ (인가 핵심)

  • 최종적으로 이 요청 URL/메서드가 요구하는 권한을 확인
  • 예:
    • /admin/**는 ADMIN 권한 필요
    • /api/**는 로그인 필요
    • 어떤 건 permitAll()로 모두 허용
➡️ 비유 : 목적지 게이트 입장권 검사(마지막 관문)

(F) 통과하면 컨트롤러

여기까지 통과하면
  • DispatcherServlet → Controller로 이동

(G) 요청 끝날 때 정리

다시 SecurityContextPersistenceFilter (요청 종료 시점)

  • 요청 처리 끝나면 SecurityContext를 정리
  • 세션 기반이면 저장
  • ThreadLocal도 청소
➡️ 비유: 출입 기록 마감/정리
 
Share article