보안은 설계 요소 중 가장 중요한 부분 중 하나이다. 이러한 보안의 개념을 스프링 시큐리티와 함께 알아보자.

1. 보안의 핵심개념 - "인증과 역할부여"

본격적인 스프링 시큐리티에 대하여 알아보기에 앞서 보안의 개념에 대하여 알아보자. 보안을 이해하는데 중요한 핵심 개념은 두 가지가 있다.

인증이란?

애플리케이션의 사용자가 해당 사용자가 주장하는 본인이 맞는지 확인하는 절차를 말한다.

인증의 방식

① 크리덴셜 기반 인증 : 사용자명과 비밀번호를 이용한 방식
② 이중인증 : ATM을 이용할 때처럼 물리적인 카드와 사용자가 입력한 개인정보를 조합하는 방식
③ 하드웨어 인증 : 자동차 키와 같은 방식

역할부여란?

인증을 통해서 인증된 주체를 하나 이상의 권한(역할)에 매핑하고 보호된 리소스에 대한 권한을 체크하는 것을 말한다.

아래의 그림을 보면 위에서 설명한 내용을 쉽게 이해할 수 있을 것이다.

인증과 인가

일반 사원인 김사원과 재무팀의 박부장은 사내 모든 직원들의 급여명세서를 열람하고 싶어한다. 먼저 시스템에 로그인을 하면 인증관리자(인증을 처리함)는 사용자가 제시한 정보를 통해 사용자가 누구인지를 확인한다. 다음으로, 접근결정 관리자는 사용자가 가지고 있는 역할을 가지고 급여명세서에 접근할 수 있는지 아닌지를 판별하게 된다.

2. 필터

스프링 시큐리티에서 웹 애플리케이션에 주로 영향을 주는 방식은 일련의 ServletRequest 필터를 사용한 방식이다. 필터들이 애플리케이션에 대한 모든 요청을 감싸서 처리한다. 스프링 시큐리티에서 여러개의 필터들은 아래 그림과 같이 체인형태를 이루면서 동작한다. 자동 설정 옵션을 사용하면 10개의 스프링 시큐리티 필터가 자동으로 설정된다.

DelegatingFilterProxy

DelegatingFilterProxy는 스프링 시큐리티가 모든 애플리케이션 요청을 감싸게 해서 모든 요청에 보안이 적용되게 하는 서블릿필터이다.(스프링 프레임워크에서 제공) 스프링 프레임워크 기반의 웹 애플리케이션에서 서블릿 필터 라이프 사이클과 연계해 스프링 빈 의존성을 서블릿 필터에 바인딩하는데 사용한다.

web.xml에 다음과 같은 설정을 해주면 애플리케이션의 모든 요청을 스프링 시큐리티가 감싸서 처리할 수 있게 된다.

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>'
필터 설명
SecurityContextPersistenceFilter SecurityContextRepository에서 SecurityContext를 로드하고 저장하는 일을 담당함
LogoutFilter 로그아웃 URL로 지정된 가상URL에 대한 요청을 감시하고 매칭되는 요청이 있으면 사용자를 로그아웃시킴
UsernamePasswordAuthenticationFilter 사용자명과 비밀번호로 이뤄진 폼기반 인증에 사용하는 가상 URL요청을 감시하고 요청이 있으면 사용자의 인증을 진행함
DefaultLoginPageGeneratingFilter 폼기반 또는 OpenID 기반 인증에 사용하는 가상URL에 대한 요청을 감시하고 로그인 폼 기능을 수행하는데 필요한 HTML을 생성함
BasicAuthenticationFilter HTTP 기본 인증 헤더를 감시하고 이를 처리함
RequestCacheAwareFilter 로그인 성공 이후 인증 요청에 의해 가로채어진 사용자의 원래 요청을 재구성하는데 사용됨 SecurityContextHolderAwareRequestFilter HttpServletRequest를 HttpServletRequestWrapper를 상속하는 하위 클래스(SecurityContextHolderAwareRequestWrapper)로 감싸서 필터 체인상 하단에 위치한 요청 프로세서에 추가 컨텍스트를 제공함
AnonymousAuthenticationFilter 이 필터가 호출되는 시점까지 사용자가 아직 인증을 받지 못했다면 요청 관련 인증 토큰에서 사용자가 익명 사용자로 나타나게 됨
SessionManagementFilter 인증된 주체를 바탕으로 세션 트래킹을 처리해 단일 주체와 관련한 모든 세션들이 트래킹되도록 도움
ExceptionTranslationFilter 이 필터는 보호된 요청을 처리하는 동안 발생할 수 있는 기대한 예외의 기본 라우팅과 위임을 처리함
FilterSecurityInterceptor 이 필터는 권한부여와 관련한 결정을 AccessDecisionManager에게 위임해 권한부여 결정 및 접근 제어 결정을 쉽게 만들어 줌

필터 체인의 제일 마지막에 위치한 FilterSecurityInterceptor는 앞에 지나온 모든 필터들의 정보를 토대로 최종 결정을 내린다.

3. 커스터마이징

스프링 시큐리티를 사용하면 보안에 관하여 대부분의 것들이 가능하지만, 기본 옵션에서 벗어난 요구사항들을 충족시키기 위해 커스터마이징하거나 확장시킬 수 있다. 이렇게 하려면 전체 스프링 시큐리티 필터 체인과 지원 인프라 스트럭처를 처음부터 하나씩 직접 설정해야 한다. 이렇게 하나씩 작성할 때에 아래의 빈 의존관계 그림을 보고 설정을 해나간다면 한결 수월할 것이다.
주의점 : 스프링 시큐리티의 필터들은 순서가 존재하며 이 순서를 어길 경우에는 예상치 못한 결과가 나올 수도 있으므로 특별한 경우가 아니라면 순서를 지켜주는 것이 좋다. (참고를 위하여 클릭하면 커질 수 있도록 큰 이미지를 사용하였다.)

필터체인

4. 기본설정과 커스터마이징 비교

① 기본 설정의 장점

  • 일반적인 웹 기반 및 메서드 기반 설정에 적용할 수 있는 강력한 기능의 축약 구문
  • 복잡한 설정을 적용하기 위해 개발자들이 내부적으로 일어나는 세부 내용에 대해 알 필요가 없다.
  • security 네임스페이스 핸들러 코드가 다양한 설정 이슈 관련 문제를 파악하고 경고해준다.
  • 설정 과정에서 필요한 부분을 빼놓고 설정할 위험이 극히 적다.

② 커스터마이징의 장점

  • 확장, 오버라이드, 표준 스프링 스택에서 의도적으로 일부를 생략하는 것과 같은 유연성을 허용한다.
  • filter-chain 엘리먼트의 pattern 어트리뷰트를 사용해 URL 패턴에 의존한 커스텀 필터 체인 및 인증을 허용한다. 이러한 기능은 웹 서비스 또는 REST 인증과 사용자 기반 인증이 함께 사용될 때 필요할 수 있다.
  • 설정 파일들이 스프링 시큐리티 네임스페이스 처리와 직접적인 연관성이 없다.
  • 인증 관리자를 명시적으로 설정하거나 오버라이드 할 수 있다.
  • 단순한 security 네임스페이스를 적용할 때보다 훨씬 더 많은 설정 옵션을 사용할 수 있다.

어느것을 선택해야 할까?

너무나도 당연한 답이지만 선택은 사용자의 몫이다. 하지만 가능하다면 기본 설정으로 사용을 하는 것이 예상하지 못한 결과를 초래하지는 않을 것이다.

namoosori
안녕하세요. 나무소리 입니다. 나무소리는 넥스트리(주)의 교육 브랜드 입니다.넥스트리가 지난 20년 동안 쌓아온 개발 및 교육 경험들을 나무소리를 통해 많은 분들과 공유 하려고 합니다.앞으로 저희 나무소리를 통해 보다 나은 교육을 경험 하실 수 있도록 구성원 모두 최선을 다하겠습니다.