본문 바로가기
개발/Programming

Acegi로 자바 애플리케이션 보안화 하기

by 카루딘 2017. 7. 20.
반응형

출처: http://foryamu.tistory.com/entry/Acegi로-자바-애플리케이션-보안화-하기-Part-1-아키텍처-개요와-보안-필터-한글 [오늘]

출처: http://foryamu.tistory.com/entry/Acegi로-자바-애플리케이션-보안화-하기-Part-1-아키텍처-개요와-보안-필터-한글 [오늘]

출처: http://foryamu.tistory.com/entry/Acegi로-자바-애플리케이션-보안화-하기-Part-1-아키텍처-개요와-보안-필터-한글 [오늘]
세 편으로 구성된 시리즈에서는 자바 엔터프라이즈 애플리케이션을 위한 막강한 오픈 소스 보안 프레임웍인 Acegi Security System을 소개합니다. 첫 번째 글에서는, 컨설턴트 Bilal Siddiqui가 Acegi의 아키텍처와 컴포넌트를 소개하고, 이것을 자바™ 엔터프라이즈 애플리케이션을 보안화 하는데 사용하는 방법을 설명합니다.

Acegi Security System은 자바 엔터프라이즈 애플리케이션을 위한 무한한 보안 코드를 작성할 수 있는 대안으로서 믿을 수 있고 사용이 편리하다. Spring 프레임웍을 사용하여 작성된 애플리케이션을 위한 것이지만, 어떤 유형의 자바 애플리케이션에도 사용될 수 있다. 세 편의 시리즈에서는 Acegi를 소개하고, 이것을 사용하여 간단한 엔터프라이즈 애플리케이션부터 보다 복잡한 애플리케이션까지 보안화 하는 방법을 설명하겠다.

소셜 북마크

mar.gar.inmar.gar.in
diggDigg
del.icio.usdel.icio.us
SlashdotSlashdot

본 시리즈는 엔터프라이즈 애플리케이션의 일반적인 보안상의 문제를 설명한 다음, Acegi로 이를 해결하는 방법을 설명한다. 애플리케이션을 보안화 하는데 사용하게 될 대부분의 기능들을 포함하고 있는 Acegi의 아키텍처 모델과 보안 필터에 대해 알아 볼 것이다. 필터들이 개별적으로 어떻게 작동하는지, 어떻게 결합되는지, 엔터프라이즈 보안 구현의 시작부터 끝까지 하나의 필터가 기능들을 어떻게 연결하는지를 배울 것이다. 이 글은 URL 기반 보안 시스템의 Acegi 구현을 보여주는 샘플 애플리케이션으로 끝을 맺는다. 본 시리즈의 후속 기술자료에서는 액세스 컨트롤 정책을 디자인 및 호스팅 하는 방법과 Acegi를 설정하는 방법을 포함하여 Acegi의 고급 사용법을 설명한다.

Acegi를 다운로드하여 예제 코드를 컴파일 하고, 샘플 애플리케이션을 실행해야 한다. 또한, Tomcat 서버를 워크스테이션의 일부로 실행해야 한다.

엔터프라이즈 애플리케이션 보안

엔 터프라이즈 콘텐트 관리(ECM) 애플리케이션은 다양한 유형의 데이터 소스(파일 시스템, 관계형 데이터 베이스, 디렉토리 서비스)에 저장된 엔터프라이즈 콘텐트의 작성 및 처리를 관리하기 때문에, ECM 보안은 그러한 데이터 소스에 대한 액세스 컨트롤을 필요로 한다. 예를 들어, ECM 애플리케이션은 디자인, 마케팅, 생산, 제조 기업의 품질 관리와 관련한 데이터를 읽거나, 편집하거나, 또는 삭제할 수 있는 권한이 누가 있는지를 관리할 수 있다.

ECM 보안 시나리오에서는 일반적으로 엔터프라이즈 리소스의 로케이터(또는 네트워크 주소)에 보안을 적용함으로써, 액세스 컨트롤을 구현한다. 이러한 간단한 보안 모델을 Universal Resource Locator, 또는 URL 보안이라고 한다. 이 글과 본 시리즈 후반에 설명하겠지만, Acegi는 URL 보안을 구현하는데 있어서 포괄적인 기능을 제공한다.

하 지만, 많은 엔터프라이즈 시나리오에서, URL 보안으로는 충분하지 않다. 예를 들어, 제조 회사에 의해 제조된 특정 제품에 대한 데이터가 들어있는 PDF 문서를 생각해 보자. 문서의 일부에는 이 회사의 디자인 부서에서 편집 및 업데이트 할 디자인 데이터가 포함되어 있다. 문서의 또 다른 부분에는 제품 관리자가 사용할 제품 데이터가 들어있다. 이와 같은 시나리오에서, 문서의 부분들마다 다른 접근 권한을 적용하는 보다 세분화 된 보안을 구현해야 한다.

이 글에서는, URL 보안을 구현하는 Acegi 장치들을 소개할 것이다. 본 시리즈 다음 글에서는 엔터프라이즈 데이터 액세스에 대한 세분화 된 컨트롤을 제공하는 프레임웍의 메소드 기반 보안을 설명하겠다.




위로



Acegi Security System

Acegi Security System은 보안 필터를 사용하여 엔터프라이즈 애플리케이션에 인증과 권한 서비스를 제공한다. 이 프레임웍은 애플리케이션의 요구 조건에 따라서 설정할 수 있는 여러 유형의 필터를 제공한다. 이 글 후반에는 다양한 유형의 보안 필터에 대해 설명한다. 지금은 다음과 같은 태스크에 Acegi의 보안 필터를 설정할 수 있다.

  1. 보안 리소스에 액세스 하기 전에 사용자에게 로그인 할 것을 요청한다. 

  2. 패스워드 같은 보안 토큰을 검사하여 사용자를 인증한다. 

  3. 인증 사용자가 보안 리소스에 액세스 할 권한이 있는지 여부를 검사한다.

  4. 성공적으로 인증 및 권한을 부여 받은 사용자를 요청된 보안 리소스로 보낸다. 

  5. 보안 리소스로 액세스 할 권한이 없는 사용자에게 Access Denied 페이지를 디스플레이 한다. 

  6. 서버에서 인증에 성공한 사용자를 기억하고, 사용자의 클라이언트에 대한 보안 쿠키를 설정한다. 그 다음 인증은 사용자에게 로그인을 요청하지 않고 쿠키를 사용하여 수행될 수 있다. 

  7. 서버 측 세션 객체에 인증 정보를 저장하여 리소스에 대한 후속 요청들을 안전하게 제공한다. 

  8. 서버 측 객체에 보안 정보의 캐시를 구현 및 관리하여 성능을 최적화 한다. 

  9. 사용자가 로그아웃 하면, 사용자의 보안 세션을 위해 관리된 서버 측 객체를 파기한다. 

  10. 사용자의 보안 정보와 ECM의 액세스 컨트롤 정책을 저장하는데 사용되는 다양한 백엔드 데이터 스토리지 서비스(디렉토리 서비스 또는 관계형 데이터베이스)와 통신한다.

Acegi의 보안 필터를 사용하면 엔터프라이즈 애플리케이션을 보안화 하는데 필요한 거의 모든 것을 수행할 수 있다.




위로



아키텍처와 컴포넌트

Acegi 를 이해할수록, Acegi 작업이 더 쉬워진다. 본 섹션에서는 Acegi의 컴포넌트를 소개하겠다. 이 프레임웍이 inversion of control (IOC)과 XML 설정 파일을 사용하여 컴포넌트를 결합하고 종속 관계를 나타내는 방법을 배우게 될 것이다.

4개의 주요 컴포넌트

Acegi Security System은 네 개의 주요 컴포넌트 유형으로 구성된다. 필터, 매니저, 프로바이더, 핸들러가 그것이다.

필터
이 컴포넌트는 인증 프로세싱, 세션 핸들링, 로그아웃 같은 일반적인 보안 서비스를 제공한다. 이 글 후반에 자세히 설명하겠다.
매니저
필터는 보안 관련 기능의 고급 추상화일 뿐이다. 매니저와 프로바이더는 인증 프로세싱과 로그아웃 서비스를 실제로 구현하는데 사용된다. 매니저는 다양한 프로바이더가 제공한 저급 보안 서비스를 관리한다.
프로바이더
다 양한 프로바이더는 디렉토리 서비스, 관계형 데이터베이스, 인-메모리 객체 같은 다양한 유형의 데이터 스토리지 서비스와 통신할 수 있다. 사용자 베이스와 액세스 컨트롤 정책들을 이 중 어떤 데이터 스토리지 서비스에도 저장할 수 있고, Acegi의 매니저가 런타임 시 적절한 프로바이더를 선택할 수 있다.
핸들러
태스크들은 가끔 여러 단계들로 나뉘며, 각 단계는 특정 핸들러에 의해 수행된다. 예를 들어, Acegi의 로그아웃 필터(logout filter) 는 두 개의 핸들러를 사용하여 HTTP 클라이언트를 로그아웃 한다. 한 개의 핸들러는 사용자의 HTTP 세션을 무효화 하고, 또 다른 핸들러는 사용자 쿠키를 파기한다. 여러 핸들러가 있으면 유연해 지고, 애플리케이션 요구 조건에 따라서 Acegi를 설정할 수 있다. 여러분에게 맞는 핸들러를 선택하여 애플리케이션을 보안화 하는데 필요한 단계를 수행한다.

Inversion of control

Acegi 의 컴포넌트는 서로 의존하여 엔터프라이즈 애플리케이션들을 보안화 한다. 예를 들어, 인증 프로세싱 필터는 인증 매니저가 올바른 인증 프로바이더를 선택해야 한다. 다시 말해서, Acegi의 컴포넌트의 의존성을 나타내고 관리할 수 있어야 한다.

IOC 구현은 자바 컴포넌트의 의존성을 관리하는데 사용된다. IOC는 두 개의 중요한 기능을 제공한다.

  1. 애플리케이션에 어떤 컴포넌트가 필요한지, 이들이 서로 어떻게 의존하는지를 나타내는 신택스를 제공한다. 

  2. 필요한 컴포넌트들이 런타임 시 사용될 수 있도록 한다.

XML 설정 파일

Acegi는 Spring 프레임웍에 있는 유명한 오픈 소스 IOC 구현을 사용하여(참고자료) 컴포넌트를 관리한다. Spring은 XML 설정 파일을 사용하여 컴포넌트의 의존성을 나타낸다. (Listing 1)


Listing 1. Spring 설정 파일의 구조

                
<beans>
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value> value here </value>
</property>
</bean>

<bean id="authenticationProcessingFilter"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFitler">
<property name="authenticationManager" ref="authManager"/>
<!-- Other properties -->
</bean>

<bean id="authManager"
class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<!-- List of providers here -->
</property>
</bean>
<!-- Other bean tags -->
</beans>


여러분도 보듯, Acegi에 의해 사용되는 Spring XML 설정 파일에는 다른 많은 <beans> 태그들을 래핑하는 하나의 <bean> 태그를 포함하고 있다. 모든 Acegi 컴포넌트들(다시 말해서, 필터, 매니저, 프로바이더)은 실제로 JavaBeans이다. XML 설정 파일에 있는 각각의 <bean> 태그는 Acegi 컴포넌트를 나타낸다.

XML 설정 파일에 대하여 

여러분이 주목해야 할 첫 번째 것은 각 <bean> 태그가 하나의 class 애트리뷰트를 갖고 있고, 이것은 컴포넌트가 사용하는 클래스를 구분한다. <bean> 태그는 id 애트리뷰트도 갖고 있는데, 이것은 Acegi 컴포넌트로서 작동하는 인스턴스(자바 객체)를 구분한다.

예를 들어, Listing 1의 첫 번째 <bean> 태그는 filterChainProxy라고 하는 컴포넌트 인스턴스를 구분하는데, 이것은 org.acegisecurity.util.FilterChainProxy라고 하는 클래스의 인스턴스이다.

빈의 의존성은 <bean> 태그의 자식 태그들을 사용하여 표현된다. 예를 들어, 첫 번째 <bean> 태그의 <property> 자식 태그를 주목하라. <property> 자식 태그는 <bean> 태그가 의존하는 값 또는 다른 빈들을 정의한다.

Listing 1에서 첫 번째 <bean> 태그의 <property> 자식 태그는 name 애트리뷰트와 <value> 자식 태그를 갖고 있는데, 각각, 빈이 의존하는 프로퍼티의 이름과 값을 정의한다.

마찬가지로, Listing 1의 두 번째 및 세 번째 <bean> 태그는 필터 빈이 매니저 빈에 의존한다는 것을 정의한다. 두 번째 <bean> 태그는 필터 빈을 나타내고, 세 번째 <bean> 태그는 매니저 빈을 나타낸다.

필터용 <bean> 태그에는 두 개의 애트리뷰트 name과 ref를 가진 <property> 자식 태그를 포함하고 있다. name 애트리뷰트는 필터 빈의 프로퍼티를 정의하고, ref 애트리뷰트는 매니저 빈의 인스턴스(이름)를 나타낸다.

다음 섹션에서는, XML 설정 파일에서 Acegi 필터를 설정하는 방법을 설명하겠다. 이 글 후반에, 샘플 Acegi 애플리케이션에서 이 필터를 사용할 것이다.




위로



보안 필터

앞 서 언급했던 것처럼, Acegi는 보안 필터를 사용하여 인증과 권한 서비스를 엔터프라이즈 애플리케이션에 제공한다. 애플리케이션 요구 사항에 따라 다양한 유형의 필터를 사용 및 설정할 수 있다. 이 섹션에서는 다섯 가지 중요한 Acegi 보안 필터를 소개하겠다.

Session Integration Filter

Acegi의 Session Integration Filter (SIF)는 일반적으로 여러분이 설정할 첫 번째 필터이다. SIF는 보안 콘텍스트 객체를 만드는데, 이것은 보안 관련 정보에 대한 플레이스홀더이다. 또 다른 Acegi 필터는 보안 콘텍스트에 보안 정보를 저장하고, 보안 콘텍스트에서 이 정보를 사용한다.

SIF 는 보안 콘텍스트를 만들고, 필터 체인에 있는 다른 필터를 호출한다. 다른 필터들은 보안 콘텍스트를 가져와서 이를 수정한다. 예를 들어, Authentication Processing Filter는 사용자 이름, 패스워드, 이메일 주소 같은 사용자 정보를 보안 콘텍스트에 저장한다.

모든 필터들이 프로세싱을 끝내면, SIF는 업데이트를 위해 보안 콘텍스트를 검사한다. 필터가 보안 콘텍스트를 수정하면, SIF는 변경 사항을 서버 측 세션 객체에 저장한다. 어떤 변화도 보안 콘텍스트에서 발견되지 않으면, SIF는 이를 버린다.

SIF는 Listing 2에서처럼 XML 설정 파일에 설정된다.


Listing 2. SIF 설정하기

                
<bean id="httpSessionContextIntegrationFilter"
class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/>


Authentication Processing Filter

Acegi는 인증에 Authentication Processing Filter (APF)를 사용한다. APF는 인증(또는 로그인) 폼을 사용하는데, 사용자는 사용자 이름과 패스워드를 입력하고, 인증을 실행한다.

APF는 클라이언트 요청에서 사용자 이름과 패스워드를 추출, 백엔드 사용자 베이스에서 사용자 매개변수 읽기, 사용자 인증에 정보 사용하기 등 모든 백엔드 인증 프로세싱 태스크를 수행한다.

APF를 설정할 때, 다음과 같은 매개변수들을 제공해야 한다.

  • 인증 매니저는 인증 프로바이더를 관리하는데 사용될 인증 매니저를 지정한다.

  • 필터 프로세스 URL은 클라이언트가 로그인 폼에서 Sign In 버튼을 누를 때 액세스 될 URL을 지정한다. URL에 대한 요청을 받으면, Acegi는 APF를 호출한다. 

  • 기본 대상 URL은 인증과 권한이 상공하면 사용자에게 제공될 페이지를 지정한다. 

  • 인증 실패 URL은 인증이 실패할 경우 사용자게 보게 될 페이지를 지정한다.

APF 는 사용자의 요청 객체에서 사용자 이름, 패스워드, 기타 정보를 내보낸다. 이것은 그 정보를 인증 매니저로 보낸다. 인증 매니저는 해당 프로바이더를 사용하여 백엔드 사용자 베이스에서 (사용자 이름, 패스워드, 이메일 주소, 사용자 액세스 권한 같은) 상세한 사용자 정보를 읽고, 사용자를 인증하고, 정보를 Authentication 객체에 저장한다.

마지막으로, APF는 Authentication 객체를 이전에 SIF에 의해 생성된 보안 콘텍스트에 저장한다. 보안 콘텍스트에 저장된 Authentication 객체는 나중에 권한 결정을 내리는데 사용될 것이다.

Listing 3과 같이 APF를 설정한다.


Listing 3. APF 설정하기

                
<bean id="authenticationProcessingFilter"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationManager"
ref="authenticationManager" />
<property name="filterProcessesUrl"
value="/j_acegi_security_check" />
<property name="defaultTargetUrl"
value="/protected/protected1.jsp" />
<property name="authenticationFailureUrl"
value="/login.jsp?login_error=1" />
</bean>


APF가 위에서 논의한 네 개의 매개변수들에 의존한다는 것을 보여주고 있다. 각 매개변수는 Listing 3의 <property> 태그로 설정된다.

Logout Processing Filter

Acegi는 Logout Processing Filer (LPF)를 사용하여 로그아웃 프로세싱을 관리한다. LPF는 클라이언트에서 로그아웃 요청이 올 때 작동한다. 클라이언트가 호출한 URL에서 로그아웃 요청을 구분한다.

LPF는 Listing 4와 같이 설정된다.


Listing 4. LPF 설정하기

                
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
<constructor-arg value="/logoutSuccess.jsp"/>
<constructor-arg>
<list>
<bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</bean>


LPF가 구조체에서 두 개의 매개변수를 취한다는 것을 알 수 있다. 로그아웃 성공 URL(/logoutSuccess.jsp) 과 핸들러 리스트가 바로 그것이다. 로그아웃 성공 URL은 로그아웃 프로세스가 완료된 후에 클라이언트를 리다이렉션 하는데 사용된다. 핸들러는 실제 로그아웃 프로세스를 수행한다. 필자는 단 한 개의 핸들러만 설정했다. HTTP 세션을 무효화 하는 데는 이것으로 충분하다. 본 시리즈 Part 2에서 핸들러에 대해 자세히 설명하겠다.

Exception Translation Filter

Exception Translation Filter (ETF)는 인증 실패와 같이 인증과 권한 절차의 예외적 상황들을 다룬다. 이러한 예외적 상황에서, ETF는 무엇을 해야 할 것인가를 결정한다.

예를 들어, 비 인증 사용자가 보호된 리소스로 접근을 시도하면, ETF는 사용자를 인증하기 위해 로그인 페이지를 제공한다. 마찬가지로, 인증 실패 시, ETF를 설정하여 Access Denied 페이지를 제공할 수 있다.

ETF는 Listing 5와 같이 설정된다.


Listing 5. ETF 설정하기

                
<bean id="exceptionTranslationFilter"
class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<bean
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.jsp" />
</bean>
</property>
<property name="accessDeniedHandler">
<bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.jsp" />
</bean>
</property>
</bean>


Listing 5에서 보듯, ETF는 authenticationEntryPoint와 accessDeniedHandler라고 하는 두 개의 매개변수를 취한다. authenticationEntryPoint 프로퍼티는 로그인 페이지를 지정하고, accessDeniedHandler는 Access Denied 페이지를 지정한다.

Interceptor filters

Acegi의 interceptor filters는 권한 결정을 내리는데 사용된다. APF가 성공적인 인증을 수행한 후에 인터셉터 필터가 작동하도록 설정해야 한다. 인터셉터는 여러분의 애플리케이션 액세스 컨트롤 정책을 사용하여 권한 결정을 내린다.

본 시리즈의 후속 기술자료에서는 액세스 컨트롤 정책 디자인 방법, 디렉토리 서비스에 이를 호스팅 하는 방법, 액세스 컨트롤 정책을 읽도록 Acegi를 설정하는 방법을 설명한다. 당분간은 Acegi를 사용하여 간단한 액세스 컨트롤 정책을 설정하는 방법을 설명하도록 하겠다. 이 글 후반에, 샘플 애플리케이션을 구현하는데 사용되는 간단한 액세스 컨트롤 정책을 살펴보도록 하겠다.

간단한 액세스 컨트롤 정책 설정은 두 단계로 나뉜다.

  1. 액세스 컨트롤 정책 작성하기.

  2. 정책에 따라 Acegi의 인터셉터 필터를 설정하기.

1 단계. 간단한 액세스 컨트롤 정책 작성하기 

Listing 6은 사용자와 사용자 역할을 정의하는 방법이다.


Listing 6. 사용자를 위해 간단한 액세스 컨트롤 정책 정의하기 

                
alice=123,ROLE_HEAD_OF_ENGINEERING


Listing 6의 액세스 컨트롤 정책은 alice라는 사용자를 정의한다. 사용자의 패스워드는 123이고, 역할은 ROLE_HEAD_OF_ENGINEERING이다. (다음 섹션에서는 하나의 파일에 사용자들과 역할들을 정의하고, Acegi Interceptor 필터가 이 파일을 사용하도록 설정하는 방법을 설명하겠다.)

2 단계. Acegi의 인터셉터 필터 설정하기 

인터셉터 필터는 권한 결정을 내리기 위해 세 개의 컴포넌트를 사용한다. 필자는 Listing 7과 같이 설정했다.


Listing 7. 인터셉터 필터 설정하기

                
<bean id="filterInvocationInterceptor"
class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager" />
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="objectDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/protected/**=ROLE_HEAD_OF_ENGINEERING
/**=IS_AUTHENTICATED_ANONYMOUSLY
</value>
</property>
<!-- More properties of the interceptor filter -->
</bean>


Listing 7에서 보듯, 설정해야 하는 세 개의 컴포넌트는 authenticationManageraccessDecisionManagerobjectDefinitionSource이다.

  • authenticationManager 컴포넌트는 Authentication Processing Filter를 소개했을 때 설명한 인증 매니저와 같은 것이다. 이 인터셉터 필터는 authenticationManager를 사용하여 권한 프로세스 동안 클라이언트를 재 인증한다. 

  • accessDecisionManager 컴포넌트는 권한 프로세스를 관리하는데, 다음 기술자료에서 상세히 설명하겠다. 

  • objectDefinitionSource 컴포넌트에는 발생하는 권한에 따른 액세스 컨트롤 정의를 포함하고 있다. 예를 들어, Listing 7의 objectDefinitionSource 프로퍼티에는 그 값에 두 개의 URL (/protected/*와 /*)를 포함하고 있다. 이 값은 이러한 URL에 대한 역할을 정의한다. /protected/* URL의 역할은 ROLE_HEAD_OF_ENGINEERING이다. 애플리케이션 요구 사항에 따라 여러분이 원하는 어떤 역할이라도 정의할 수 있다. 

    alice라는 사용자에 ROLE_HEAD_OF_ENGINEERING을 정의했던 Listing 6을 상기해 보라. alice는 /protected/* URL에 액세스 할 수 있다.




위로



필터 작동 방법

이미 배웠겠지만, Acegi의 컴포넌트는 서로 종속되어 애플리케이션을 보안화 한다. 이 글 후반에, 지정된 순서로 보안 필터를 적용하도록 Acegi를 설정하는 방법과 필터 체인을 만드는 방법을 설명하겠다. 이를 위해, Acegi는 필터 체인 객체를 관리하는데, 이것은 애플리케이션을 보안화 하기 위해 설정했던 모든 필터들을 래핑한다. 그림 1은 Acegi 필터 체인의 라이프 사이클을 보여주고 있다. 클라이언트가 HTTP 요청을 애플리케이션으로 보낼 때 시작한다. (그림 1은 브라우저 클라이언트를 제공하는 컨테이너이다.)


그림 1. 브라우저 클라이언트를 안전하게 제공하기 위해 Acegi의 필터 체인을 호스팅 하고 있는 컨테이너
Acegi 필터의 라이프 사이클 

다음 단계는 필터 체인의 라이프 사이클이다.

  1. 브라우저 클라이언트가 HTTP 요청을 애플리케이션으로 보낸다. 

  2. 컨 테이너가 HTTP 요청을 받고, HTTP 요청에 포함된 정보를 래핑하는 요청 객체를 만든다. 컨테이너 역시 응답 객체를 만드는데, 다른 필터들은 요청 클라이언트에 HTTP 응답을 준비하기 위해 처리될 수 있다. 컨테이너는 Acegi의 필터 체인 프록시, 즉 프록시 필터를 호출한다. 프록시는 실제 필터들이 적용될 순서를 알고 있다. 컨테이너가 프록시를 호출하면, 이것은 요청, 응답, 필터 체인 객체를 여기로 전달한다. 

  3. 프록시 필터는 필터 체인에 첫 번째 필터를 호출하면서, 요청, 응답, 필터 체인 객체를 필터로 전달한다. 

  4. 체 인에 있는 필터들은 하나씩 프로세싱을 수행한다. 하나의 필터는 체인에 있는 다음 필터를 호출함으로써 프로세싱을 종료한다. 필터는 어떤 프로세싱도 하지 않을 수도 있다. (예를 들어, APF는 인커밍 요청이 인증을 요하지 않는다는 것을 알면 프로세싱을 종료한다.) 

  5. 인증 필터가 프로세싱을 끝내면, 요청과 응답 객체를 애플리케이션에 설정된 인터셉터 필터로 전달한다. 

  6. 인터셉터는 요청 클라이언트가 요청을 받은 리소스로 액세스 할 권한이 있는지를 결정한다. 

  7. 인터셉터는 컨트롤을 애플리케이션으로 전달한다. (예를 들어, 성공적인 인증과 권한이 된 경우 클라이언트에 의해 요청된 JSP 페이지)

  8. 애플리케이션은 응답 객체에 대해 콘텐트를 작성한다. 

  9. 응답 객체는 이제 준비가 되었다. 컨테이너는 응답 객체를 HTTP 응답으로 변환하고, 응답을 요청 클라이언트로 보낸다. 

Acegi 필터를 더욱 잘 이해할 수 있도록, Session Integration Filter와 Authentication Processing Filter의 작동 모습을 자세히 설명하도록 하겠다.

SIF가 보안 콘텍스트를 생성하는 방법

그림 2는 SIF의 보안 콘텍스트 생성에 관한 단계이다.


그림 2. SIF가 보안 콘텍스트를 만든다. 
SIF가 보안 콘텍스트를 만드는 방법 

이 단계들을 자세히 살펴보자.

  1. Acegi의 필터 체인 프록시는 SIF를 호출하고 요청, 응답, 필터 체인 객체를 여기로 전달한다. 일반적으로 SIF를 필터 체인의 첫 번째 필터로 설정한다. 

  2. SIF 는 이것이 웹 요청을 이미 처리했는지 여부를 검사한다. 처리했다는 것을 알게 되면 어떤 프로세싱도 수행하지 않고 컨트롤을 필터 체인의 다음 필터로 전달한다. (아래 4 단계). SIF가 웹 요청 동안 처음 호출된 것이라는 것을 알게 되면, 플래그를 설정하는데, 이것은 SIF가 호출되었다는 것을 표시하는데 사용될 것이다. 

  3. SIF는 세션 객체가 존재하는지, 보안 콘텍스트를 포함하고 있는지 여부를 검사한다. 세션 객체에서 보안 콘텍스트를 가져오고, 이것을 보안 콘텍스트 홀더(security context holder) 라고 하는 임시 플레이스홀더에 저장한다. 세션 객체가 존재하지 않으면, SIF는 새로운 보안 콘텍스트를 만들고, 이것을 보안 콘텍스트 홀더에 둔다. 보안 콘텍스트 홀더는 애플리케이션 범위 내에 존재하기 때문에 다른 보안 필터에도 접근할 수 있다. 

  4. SIF는 필터 체인의 다음 필터를 호출한다. 

  5. 다음 필터들은 보안 콘텍스트를 편집한다. 

  6. SIF는 필터 체인 프로세싱이 완료한 후에 컨트롤을 받는다. 

  7. SIF 는 다른 필터가 프로세싱 동안 보안 콘텍스트를 변경했는지를 검사한다. (예를 들어, APF는 보안 콘텍스트에 사용자 상세를 저장한다.) 그렇다면, 세션 객체에 보안 콘텍스트를 업데이트 한다. 필터 체인 프로세싱 동안 보안 콘텍스트에 대한 변경 사항은 세션 객체에 있게 된다.

APF가 사용자를 인증하는 방법

그림 3은 APF의 사용자 인증 단계이다.


그림 3. APF의 사용자 인증
APF의 사용자 인증 방법 

이 단계를 자세히 살펴보자.

  1. 필터 체인의 이전 필터는 요청, 응답, 필터 체인 객체를 APF에 전달한다. 

  2. APF는 요청 객체에서 파견된 사용자 이름, 패스워드, 기타 정보들로 인증 토큰을 만든다. 

  3. APF는 인증 토큰을 인증 매니저로 전달한다. 

  4. 인증 매니저에는 한 개 이상의 인증 프로바이더가 포함된다. 각 프로바이더는 정확히 한 가지 유형의 인증을 지원한다. 매니저는 어떤 프로바이더가 APF에서 받은 인증 토큰을 지원하는지를 검사한다. 

  5. 인증 매니저는 인증 토큰을 인증에 적합한 프로바이더로 전달한다. 

  6. 인증 프로바이더는 인증 토큰에서 사용자 이름을 추출하고, 이를 user cache service라 고 하는 서비스로 전달한다. Acegi는 인증을 받은 사용자 캐시를 관리한다. 다음 번에 그 사용자가 로그인 하면, 백엔드 데이터 스토리지에서 읽는 대신, Acegi는 캐시에서 사용자의 상세(사용자 이름, 패스워드, 권한)를 로딩한다. 이는 성능을 향상시킨다. 

  7. 사용자 캐시 서비스는 사용자 상세가 캐시에 존재하는지 여부를 검사한다. 

  8. 사용자 캐시 서비스는 사용자의 상세를 인증 프로바이더로 리턴한다. 캐시가 사용자 상세를 포함하고 있지 않으면, null을 리턴한다. 

  9. 인증 프로바이더는 캐시 서비스가 사용자 상세 또는 null 중 어떤 것을 리턴했는지를 검사한다. 

  10. 캐시가 null을 리턴하면, 인증 프로바이더는 사용자 이름(6 단계에서 추출)을 user details service라고 하는 또 다른 서비스로 전달한다. 

  11. 사용자 상세 서비스는 사용자의 상세를 포함하고 있는 백엔드 데이터 스토리지(디렉토리 서비스)와 통신한다. 

  12. 사용자 상세 서비스는 사용자의 상세를 리턴하고 사용자 상세를 찾지 못할 경우 인증 예외를 던진다. 

  13. 사 용자 캐시 서비스나 사용자 상세 서비스가 유효 사용자 상세를 리턴하면, 인증 프로바이더는 사용자게 제공한 (패스워드 같은) 보안 토큰을 캐시 또는 사용자 상세 서비스에 의해 리턴된 패스워드와 맞춰본다. 매치되면, 인증 프로바이더는 사용자 상세를 인증 매니저에게 리턴한다. 그렇지 않을 경우, 인증 예외를 던진다. 

  14. 인증 매니저는 사용자 상세를 APF로 리턴한다. 사용자는 이제 성공적으로 인증이 된 것이다. 

  15. APF는 그림 2의 3 단계에서 생성된 보안 콘텍스트에 사용자 상세를 저장한다. 

  16. APF는 컨트롤을 필터 체인의 다음 필터로 전달한다.




위로



간단한 Acegi 애플리케이션

지금까지 Acegi에 대해 많은 것을 배웠으므로, 배운 것을 토대로 무엇을 할 수 있는지를 설명하도록 하겠다. 설명을 위해 필자는 샘플 애플리케이션을 디자인 했고(다운로드), 일부 리소스를 보안화 하도록 Acegi를 설정했다.

샘플 애플리케이션에는 다섯 개의 JSP 페이지가 포함된다: index.jsp, protected1.jsp, protected2.jsp, login.jsp, accessDenied.jsp.

index.jsp는 애플리케이션의 Welcome 페이지이다. 사용자에게 세 개의 하이퍼 링크를 제공한다. (그림 4)


그림 4. 샘플 애플리케이션의 Welcome 페이지 
간단한 Acegi 애플리케이션 

그 림 4의 링크들 중 두 개는 보호 리소스(protected1.jsp와protected2.jsp)를, 세 번째 링크는 로그인 페이지(login.jsp)를 가리킨다. accessDenied.jsp 페이지는 Acegi가 사용자가 보호 리소스에 액세스 할 권한이 없다는 것을 알아낼 경우에만 제공된다.

사용자가 보호 리소스로의 액세스를 시도하면, 샘플 애플리케이션은 로그인 페이지를 제공한다. 사용자는 로그인 페이지를 통해 로그인 하고, 애플리케이션은 자동으로 요청을 받은 보호 리소스로 리다이렉션 한다.

사 용자는 Welcome 페이지에서 세 번째 링크(Login)를 클릭함으로써, 로그인 페이지를 직접 요청한다. 이 경우, 애플리케이션은 사용자가 로그인 할 수 있는 로그인 페이지를 제공한다. 로그인 후, 애플리케이션은 사용자를 protected1.jsp로 리다이렉션 하는데, 이것은 사용자가 특정 보호 리소스를 요청하지 않고 사용자가 로그인 할 때마다 제공되는 기본 리소스이다.

샘플 애플리케이션 설정하기

이 글의 소스 코드 다운로드에는 acegi-config.xml이라고 하는 XML 설정 파일이 포함되어 있는데, 여기에는 Acegi 필터의 설정이 포함되어 있다. 이 설정은 보안 필터에 관한 논의에 나왔던 예제에 기반하고 있다.

또한 샘플 애플리케이션을 위해 web.xml 파일도 작성했다. (Listing 8)


Listing 8. 샘플 애플리케이션을 위한 web.xml 파일

                
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/acegi-config.xml</param-value>
</context-param>
<filter>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<filter-class>
org.acegisecurity.util.FilterToBeanProxy
</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>
org.acegisecurity.util.FilterChainProxy
</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>


web.xml 파일은 다음을 설정한다.

  • <context-param> 태그에 acegi-config.xml 파일의 URL.

  • <filter> 태그에 Acegi의 필터 체인 프록시 클래스의 이름.

  • <filter-mapping>에서 URL과 Acegi의 필터 체인 프록시의 매핑. 애플리케이션의 모든 URL들을(/*) Acegi의 필터 체인 프록시로 매핑할 수 있다. Acegi는 보안을 Acegi의 필터 체인 프록시로 매핑하는 모든 URL에 적용한다.

  • <listener> 태그의 애플리케이션 콘텍스트 로더는 Spring의 IOC 프레임웍을 로딩한다.

애플리케이션 전개 및 실행하기

샘플 애플리케이션의 전개와 실행은 매우 간단하다. 두 가지만 하면 된다.

  1. 튜토리얼의 소스 코드 다운로드의 acegisample.war 파일을 Tomcat의 webapps 디렉토리에 복사한다. 

  2. Acegi Security System 홈페이지에서 acegi-security-1.0.3.zip을 다운로드하 여 압축을 해제한다. acegi-security-sample-tutorial.war 라고 하는 샘플 애플리케이션을 찾는다. war 파일의 압축을 풀어, 모든 jar를 WEB-INF/lib 폴더로 추출한다. WEB-INF/lib의 모든 JAR를 theacegisample.war 애플리케이션의 WEB-INF/lib 폴더로 복사한다.

이제 샘플 애플리케이션을 실행할 준비가 되었다. Tomcat을 시작하고 브라우저에서 http://localhost:8080/acegisample/로 간다.

그림 4에서 보았던 Welcome 페이지를 보겠지만, 이번에는 살아있다. 계속 진행하여 Welcome 페이지에 제공된 다른 링크에 액세스 할 때 어떤 일이 발생하는지를 보라.




위로



결론

Acegi로 자바 애플리케이션 보안화 하기 시리즈의 첫 번째 글에서는 Acegi Security System의 기능, 아키텍처, 컴포넌트에 대해 배웠다. 또한 보안 프레임웍의 필수 요소인 Acegi의 보안 필터에 대해서도 배웠다. XML 설정 파일을 사용하여 컴포넌트 의존성을 설정하는 방법도 배웠고, URL 기반 보안을 구현하는 샘플 애플리케이션에서 작동하는 Acegi의 보안 필터도 보았다.

이 글에서 설명한 보안 기술은 매우 간단하고, 이를 구현하는데 사용되는 Acegi 장치 역시 간단하다. 다음 글에서는 액세스 컨트롤 정책을 작성하는 것부터 디렉토리 서비스에 저장하기까지 보다 고급 주제를 다루도록 하겠다. 또한, 디렉토리 서비스와 상호 작동하여 액세스 컨트롤 정책을 구현하도록 Acegi를 설정하는 방법도 설명할 것이다.



반응형