/spring-security-basic-practice

스프링 시큐리티 기초 공부

Primary LanguageKotlin

Spring Security Basic Practice

Spring Security는 인증(Authentication) 및 인가(Authorization)를 담당하는 스프링 프레임워크이다. 먼저 ChatGPT에게 Spring Security에 대해 물어봤는데 정확하고 상세하게 대답해줘서 놀랐다. chatgpt-what-is-spring-security.png

누군가 Spring Security에 대해 물어본다면 ChatGPT처럼 말하면 아주 좋을 것 같다. (대단;;) 이번 블로깅에서는 Spring Security의 기초 구조에 대해 정리해보려고 한다.

Basic Web Security

web-security.png

Servlet 기반으로 구동되는 웹서비스는 인증, 인가, 변환, 압축, 암호화 등 비즈니스 로직이 수행되기 전에 공통으로 사용되는 로직을 Servlet Filter로 구현한다. 위 그림처럼 Servlet이 웹 요청을 처리하기 앞서 여러 Filter가 순서에 맞춰 수행되는 것이 Servlet 서버의 기본 동작 흐름이다.

Spring Security

filter-chain-proxy.png

Spring Security는 FilterChainProxy라는 물리 Filter 한 개를 필터 흐름에 끼워 넣는데, 이 프록시는 내부적으로 FilterChain이라는 Filter 복합체 여러개를 가지며 FilterChain 한 개는 많은 Filter를 가진다.

public interface SecurityFilterChain {
    boolean matches(HttpServletRequest request);
    List<Filter> getFilters();
}

FilterChainProxy는 가지고 있는 FilterChain 중 현재 웹 요청(HttpServletRequest)을 지원하는 첫 번째 chain을 선택하여 해당 chain의 Filter들을 수행한다. SecurityFilterChain interface의 matches 메서드를 이용해서다.

개발자는 Spring Security에서 기본적으로 제공하는 FilterChain 리스트 외에 커스텀 FilterChain을 추가하여 서비스의 보안 요구사항을 만족시키는 작업을 해야한다.

Thread Bounded Security Context

Servlet은 웹 요청마다 하나의 thread로 동작하는데, Spring Security에서도 thread 단위로 현재의 인증된 Principal(인증 주체)를 저장한다. 인증된 principal을 Authentication interface로 지칭하며 이 객체는 SecurityContext에 포함된다.

인증된 객체의 정보를 접근하는 방법은 3가지 정도 있다.

  1. SecurityContextHolder (흔히 쓰이지는 않음)
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
User = (User) authentication.getPrincipal();
  1. @AuthenticationPrincipal
@RequestMapping("/foo")
public String foo(@AuthenticationPrincipal User user) {
}
  1. Principal
@RequestMapping("/foo")
public String foo(Principal principal) {
    Authentication authentication = (Authentication) principal;
    User user = (User) authentication.getPrincipal();
}

HttpSecurity 분석

References