Spring 7기 프로젝트/뉴스피드 팀 프로젝트

Spring Security 작동 순서 정리

JuNo_12 2025. 5. 26. 17:49

나의 코드에서 작동하는 방식

요청 → 인증 → 인가 → 컨트롤러 → 서비스 → DB

 

 

1. 클라이언트가 API 요청

예: POST /api/schedules (일정 등록 요청)

 

2. Spring Security Filter Chain 작동

  • Spring Security가 HTTP 요청을 가로채서 인증 및 권한 확인
  • SecurityFilterChain에 정의된 필터들 실행
  • 예를 들어, 세션에서 인증 정보 읽어 SecurityContextHolder에 세팅
  • 현재 요청에 대해 인증이 없으면 401 Unauthorized 처리 (CustomAuthenticationEntryPoint 실행)
  • 요청이 /api/users/signup이나 /api/auth/login이 아니면 인증이 있어야 통과
클라이언트 로그인 요청
         ↓
   AuthService.login()
         ↓
authenticationManager.authenticate(...)
         ↓
   CustomUserDetailsService.loadUserByUsername(email)
         ↓
  사용자 DB 조회 (User 엔티티 반환)
         ↓
   CustomUserDetails(user) 생성
         ↓
UsernamePasswordAuthenticationToken(authentication 객체) 생성
 (principal = CustomUserDetails)
         ↓
SecurityContext context = SecurityContextHolder.getContext()
context.setAuthentication(authentication)
         ↓
SecurityContextHolder 내에 Authentication 객체 저장됨
 (Authentication -> CustomUserDetails 포함)

 

이후 요청 시

요청 처리 시
         ↓
SecurityContextHolder.getContext().getAuthentication()
         ↓
Authentication 객체 획득
         ↓
authentication.getPrincipal() → CustomUserDetails 반환
         ↓
User 정보 활용 가능

 

3. 인증된 사용자 정보 확인

  • 인증 성공한 경우, SecurityContextHolder.getContext().getAuthentication() 내부에 CustomUserDetails가 담겨 있음
  • 이때 @AuthenticationPrincipal UserDetails userDetails가 컨트롤러 메서드 인자에 주입됨
  • userDetails.getUsername()은 이메일 주소를 반환 (즉, CustomUserDetails.getUsername())

 

4. 컨트롤러 (ScheduleController) 호출

  • 스프링 MVC가 요청 URL과 HTTP 메서드를 기반으로 ScheduleController의 해당 핸들러 메서드 실행
  • 예: createSchedule() 메서드가 호출됨

 

더보기

1. 인증 시점 (AuthService.login())

  • 사용자가 로그인 시도 → AuthenticationManager가 인증 처리 → 인증 성공 시 Authentication 객체가 만들어짐 (여기엔 CustomUserDetails 포함).
  • 이 Authentication 객체를 SecurityContextHolder.getContext().setAuthentication(authentication) 으로 저장.

2. 인증 정보 저장 위치

  • SecurityContextHolder는 스레드 로컬(ThreadLocal)에 SecurityContext를 저장해서 현재 쓰레드에서만 접근 가능하게 함.
  • 그러나 HTTP 요청이 여러 번 오고 나갈 때마다 쓰레드가 바뀌기 때문에,
  • Spring Security는 이 SecurityContext를 세션(HttpSession)에 저장함 (HttpSessionSecurityContextRepository가 담당).
  • 이렇게 하면 클라이언트가 보내는 세션 ID 쿠키를 통해, 다음 요청 때도 인증 정보를 찾을 수 있음.

3. 이후 요청에서 인증 정보 접근

  • 클라이언트가 서버에 요청을 보낼 때마다,
  • Spring Security 필터가 세션에서 SecurityContext를 읽어 SecurityContextHolder에 세팅.
  • 그래서 컨트롤러, 서비스 어디서든 SecurityContextHolder.getContext().getAuthentication() 으로 인증 정보에 접근 가능.
  • 이 Authentication 안에 CustomUserDetails가 있고, 그걸 통해 현재 로그인된 유저 정보 조회 가능.

 

내부 호출 흐름 요약 (예: 일정 등록)

HTTP Request (POST /api/schedules)
   ↓
Spring Security FilterChain
   ↓
인증 성공 → SecurityContextHolder에 인증정보 저장
   ↓
ScheduleController.createSchedule()
   ↓
userService.findByEmailAddressOrThrow(userDetails.getUsername())
   ↓
ScheduleService.createSchedule()
   ↓
  findUserById(userId)
   ↓
  scheduleRepository.save(new Schedule(...))
   ↓
ScheduleCreationResponseDto 반환
   ↓
ScheduleController → ResponseEntity 반환
   ↓
HTTP Response