🍃 Spring Security란?
스프링에서 제공하는 모듈 중 하나로, 스프링을 기반으로 하는 보안 프레임워크이다.
Spring Security 를 통해 자체적으로 세션 체크, 리다이렉션 등을 추상화하여, 보다 편하게 구현하도록 돕는다.
Spring Security는 스프링 의존성을 없애기 위해 Filter 인터페이스를 기반으로 동작한다.
즉, 기존의 Spring MVC, 비즈니스 로직과 완벽하게 분리하여 관리 및 동작할 수 있다.
또, 개발자가 직접 만들어야할 필터들을 기본으로 제공해준다. 이렇게 제공하는 필터들을 SecurityFilterChain 이라 한다.
SecurityFilterChain 들의 종류와 특징들은 아래에서 다루겠다.
🔐 인증과 인가
- 인증(Authentication)은 누구인지 식별하고, 입증하는 과정
- 인가(Authorized)는 인증이 완료된 사용자의 권한을 설정하는 과정
- 접근 주체(Principle)는 보호된 대상에 접근하는 유저 혹은 시스템
- 역할(Role)에 따라 다른 권한을 부여해야한다.
🔊 서블릿과 필터
인증과 인가를 담당하는 코드는 기존 서비스와 함께 작성될 수 있다.
하지만, 인증 및 인가 코드는 핵심 비즈니스 로직과는 전혀 관련이 없으며, 보안이 요구되는 모든 컴포넌트에
같은 보안 코드를 반복할 경우, 수정했을 때 아무런 상관없는 영역까지 변경이 전파되는 상당한 큰 단점이 있다.
그렇기에 서블릿 2.3 부터는 필터라는 개념이 추가되었다. 서블릿과 유사하지만, Request와 Response를 먼저 받아
조작할 수 있다는 차이점이 존재한다.
스프링 MVC 는 프론트 컨트롤러 패턴을 사용하여, 요청을 처리한다.
쉽게 풀어서 설명하자면, 단 하나의 Dispatcher Servlet 을 이용하여 요청을 받고, 서비스를 추상화한다는 의미이다.
즉, 스프링에서도 필터를 그대로 사용할 수 있다.
@ServletComponentScan
@WebServlet(name = "loadFilter", urlPattern = {"/*"}, loadOnStartup = 1}
public class LoadFilter {
...
}
스프링 부트를 사용하여 다음과 같이 구성도 가능하다.
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean logFilter() {
FilterRegistrationBean<Filter> filterBean = new FilterRegistrationBean<>();
filterBean.setFilter(new LogFilter());
filterBean.setOrder(1);
filterBean.addUrlPatterns("/*");
return filterBean;
}
}
혹은 @ServletComponentScan 과 Filter 인터페이스를 구현한 구현체에 @WebFilter 어노테이션을 추가해주는 방법 역시
사용 가능하다.
(자세한 정보는 https://taetaetae.github.io/2020/04/06/spring-boot-filter/ 참고하길 바란다.)
✂ 스프링 인터셉터
서블릿은 자바 웹 표준에서 제공하나, 인터셉터는 스프링 MVC 에서만 제공하는 기능이다.
서블릿과 관계없이 Dispatcher Servlet 에서 컨트롤러에 가기 전에 실행된다.
즉, Spring MVC 의 핵심인 Dispatcher Servlet 에서 동작하는 모든 객체와 예외들에 접근할 수 있다.
- preHandle (boolean)
- 컨트롤러에 가기전에 호출되는 메소드
- 반환값이 true 이면 다음 인터셉터가 호출되고, 그렇지 않다면 컨트롤러를 바로 호출한다.
- postHandle (boolean)
- 컨트롤러의 return 이후 호출되는 메소드
- 뷰에 전달할 Model 를 조작할 수 있다.
- afterCompletion
- HTML 뷰가 렌더링된 이후에 호출되는 메소드
⚠ 주의할 점
postHandle 메소드는 컨트롤러에 예외가 발생할 경우, 호출되지 않는다.
반면에 afterCompletion 메소드는 예외와 상관없이 항상 호출된다.
⚔ 필터 VS 인터셉터
필터는 J2EE 표준 스펙에 정의되어 있는 기술이기에, Spring Framework 에 의존적이지 않다.
반면, 인터셉터는 스프링에서만 사용할 수 있는 기술이다.
웹 애플케이션에 전역적으로 처리해야하는 기능은 필터로 처리하는 것이 좋고, 클라이언트에 들어오는 디테일한 처리는
인터셉터의 다양한 기능으로 처리하는 것이 좋다고 한다.
참고: https://mangkyu.tistory.com/173
🌫 스프링 필터
스프링에서는 서블릿 요청이 들어오면, 스프링 컨테이너와 연결할 수 있는 DelegationFilterProxy 라는
서블릿 필터를 제공한다.
DelegationFilterProxy 를 통해 스프링 빈으로 구현한 필터를 등록하고, 서블릿 표준 필터처럼 동작하게 된다.
즉, Spring Security 가 Filter 를 사용해서 구현했다는 것은 DelegationFilterProxy 를 통해 필터를 등록했다는 뜻이다.
Spring Security 는 FilterChainProxy 를 통해 다양한 필터 기능을 구현하며, 이는 스프링 빈이기에 DelegationFilterProxy 를
통해 필터에 추가된다.
☄ FilterChainProxy
Spring Security 에서 제공하는 특수 필터로 다양한 인스턴스를 SecurityFilterChain 을 통해 위임하고 있다.
일종의 스프링 시큐리티를 위한 전용 Dispatcher Servlet 이라 생각하면 된다.
SecurityChainFilter
- SecurityContextPersistenceFilter
- SecurityContextRepository 에서 SecurityContext 를 조회 및 저장
- LogoutFilter
- 설정된 로그아웃 URL 로 오는 요청을 감시 및 해당 유저 로그아웃 처리
- UsernamePasswordAuthenticationFilter
- Form 기반 인증에서 설정된 로그인 URL 로 오는 요청을 감시 및 유저 인증 처리
- AuthenticationManager 를 통한 인증
- 인증 성공시, 얻은 Authentication 객체를 SecurityContext 에 저장, AuthenticationSuccessHandler 실행
- 인증 실패시, AuthenticationFailureHandler 실행
- DefaultLoginPageGeneratingFilter
- 인증을 위한 로그인 폼 URL 감시
- BasicAuthenticationFilter
- HTTP 기본 인증 헤더를 감시 및 처리
- RequestCacheAwareFilter
- 로그인 성공 후, 원래 요청 정보를 제구성하기 위해 사용된다.
- SecurityContextHolderAwareRequestFilter
- HttpServletRequestWrapper 를 상속한 SecurityContextHolderAwareRequestWrapper 클래스로
HttpServletRequest 정보를 감싼다. - SecurityContextHolderAwareRequestWrapper 는 필터 체인에게 다음 필터들에게 정보를 제공한다.
- HttpServletRequestWrapper 를 상속한 SecurityContextHolderAwareRequestWrapper 클래스로
- AnonymousAuthenticationFilter
- 사용자 정보가 인증되지 않았다면, 인증 토큰에 사용자가 익명 사용자로 나타난다.
- SessionManagementFilter
- 인증된 사용자와 관련된 모든 세션을 추적한다.
- ExceptionTranslationFilter
- 보호된 요청을 처리하는 도중, 발생할 수 있는 예외를 위임 및 전달한다.
- FilterSecurityInterceptor
- AccessDecisionManager 로써 권한 부여 처리를 위임하여 접근 제어를 쉽게 해준다.
이상입니다.
'Spring > 공부' 카테고리의 다른 글
[Spring/공부] Custom Interceptor (0) | 2023.03.08 |
---|---|
[Spring Core] 스프링 빈 생명주기와 스코프 (0) | 2023.01.14 |
[Spring Core] 컴포넌트 스캔과 의존성 주입 (0) | 2023.01.14 |
[Spring Core] 스프링 컨테이너와 스프링 빈 (0) | 2023.01.11 |